[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Mon Mar 7 13:39:05 UTC 2016


The branch master has been updated
       via  a193388811db7e842ed7d1966bbe2552095b26cc (commit)
       via  e2524943ce669ec1f2d4dfd27652d175e48cf848 (commit)
       via  d245844010bb4ae9867d43edd39782280cc671f8 (commit)
       via  15457b620397d7fd671df6eea8055a18baf68699 (commit)
       via  8da00a38cd931f66ad4f1aaae6003d4dd6bc65c0 (commit)
       via  6cba4a66619dfb2c5cb784fe5aa5677cafbf9a33 (commit)
       via  7f458a48ff3a231d5841466525d2aacbcd4f6b77 (commit)
      from  b63447c1150f659cfc54ed290df33345e8ce7cbd (commit)


- Log -----------------------------------------------------------------
commit a193388811db7e842ed7d1966bbe2552095b26cc
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Mar 7 12:36:20 2016 +0000

    Fix some clang warnings
    
    The af_alg engine and associated test were creating warnings when compiled
    with clang. This fixes it.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit e2524943ce669ec1f2d4dfd27652d175e48cf848
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Mar 3 14:56:10 2016 +0000

    Fix minor errors in the afalg test
    
    The new afalg test should have a copyright date of 2016. Also an
    incorrect buffer was being sent to EVP_CipherFinal_ex when
    decrypting.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit d245844010bb4ae9867d43edd39782280cc671f8
Author: clucey <catriona.lucey at intel.com>
Date:   Thu Mar 3 05:56:10 2016 +0000

    Adding afalg test
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 15457b620397d7fd671df6eea8055a18baf68699
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 29 16:14:00 2016 +0000

    Fix OPENSSL_INIT flags to avoid a clash.
    
    The 0x00010000L OPENSSL_INIT flag appeared twice.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 8da00a38cd931f66ad4f1aaae6003d4dd6bc65c0
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Feb 29 13:36:47 2016 +0000

    Misc afalg build fixes
    
    Misc afalg build fixes as suggested by Richard Levitte for the latest
    Configure changes.
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>

commit 6cba4a66619dfb2c5cb784fe5aa5677cafbf9a33
Author: clucey <catriona.lucey at intel.com>
Date:   Tue Feb 23 08:01:01 2016 +0000

    Rework based on feedback:
    1. Cleaned up eventfd handling
    2. Reworked socket setup code to allow other algorithms to be added in
       future
    3. Fixed compile errors for static build
    4. Added error to error stack in all cases of ALG_PERR/ALG_ERR
    5. Called afalg_aes_128_cbc() from bind() to avoid race conditions
    6. Used MAX_INFLIGHT define in io_getevents system call
    7. Coding style fixes
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 7f458a48ff3a231d5841466525d2aacbcd4f6b77
Author: clucey <catriona.lucey at intel.com>
Date:   Wed Feb 17 13:38:36 2016 +0000

    ALG: Add AFALG engine
    
    Reviewed-by: Richard Levitte <levitte at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 Configure                                          |  20 +
 Makefile.in                                        |   3 +
 crypto/include/internal/cryptlib_int.h             |   2 +-
 crypto/include/internal/engine.h                   |   1 +
 crypto/init.c                                      |  20 +-
 engines/Makefile.in                                |  14 +-
 engines/afalg/Makefile.in                          |  78 ++
 engines/afalg/build.info                           |  13 +
 engines/afalg/e_afalg.c                            | 850 +++++++++++++++++++++
 engines/afalg/e_afalg.ec                           |   1 +
 crypto/kdf/kdf_err.c => engines/afalg/e_afalg.h    |  87 ++-
 engines/{e_chil_err.c => afalg/e_afalg_err.c}      | 112 +--
 .../afalg/e_afalg_err.h                            |  61 +-
 include/openssl/crypto.h                           |   1 +
 include/openssl/engine.h                           |   2 +
 test/Makefile.in                                   |  11 +-
 test/{memleaktest.c => afalgtest.c}                | 110 ++-
 test/build.info                                    |   6 +-
 .../{90-test_networking.t => 30-test_afalg.t}      |  59 +-
 19 files changed, 1252 insertions(+), 199 deletions(-)
 create mode 100644 engines/afalg/Makefile.in
 create mode 100644 engines/afalg/build.info
 create mode 100644 engines/afalg/e_afalg.c
 create mode 100644 engines/afalg/e_afalg.ec
 copy crypto/kdf/kdf_err.c => engines/afalg/e_afalg.h (63%)
 copy engines/{e_chil_err.c => afalg/e_afalg_err.c} (51%)
 copy demos/engines/cluster_labs/hw_cluster_labs_err.h => engines/afalg/e_afalg_err.h (62%)
 copy test/{memleaktest.c => afalgtest.c} (53%)
 copy test/recipes/{90-test_networking.t => 30-test_afalg.t} (65%)

diff --git a/Configure b/Configure
index 305820b..174fe15 100755
--- a/Configure
+++ b/Configure
@@ -1175,6 +1175,26 @@ else               { $no_user_defines=1;    }
 
 # ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
 
+$config{afalg}="";
+if ($target =~ m/^linux/) {
+    my $minver = 4*10000 + 1*100 + 0;
+    if ($config{cross_compile_prefix} eq "") {
+        my $verstr = `uname -r`;
+        my ($ma, $mi1, $mi2) = split("\\.", $verstr);
+        ($mi2) = $mi2 =~ /(\d+)/;
+        my $ver = $ma*10000 + $mi1*100 + $mi2;
+        if ($ver < $minver) {
+            $disabled{afalg} = "too-old-kernel";
+        } else {
+            push @{$config{engdirs}}, "afalg";
+        }
+    }
+} else {
+    $disabled{afalg}  = "not-linux";
+}
+
+push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalg});
+
 # If we use the unified build, collect information from build.info files
 my %unified_info = ();
 
diff --git a/Makefile.in b/Makefile.in
index 9fcdb39..892a208 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -230,6 +230,8 @@ INSTALLDIRS=	\
 		$(DESTDIR)$(OPENSSLDIR)/certs \
 		$(DESTDIR)$(OPENSSLDIR)/private
 
+ENGDIRS={- join(" ", @{$config{engdirs}}) -}
+
 all: Makefile build_all_but_tests
 
 # as we stick to -e, CLEARENV ensures that local variables in lower
@@ -275,6 +277,7 @@ BUILDENV=	LC_ALL=C PLATFORM='$(PLATFORM)' PROCESSOR='$(PROCESSOR)'\
 		AES_ENC='$(AES_ENC)' CMLL_ENC='$(CMLL_ENC)'	\
 		BF_ENC='$(BF_ENC)' CAST_ENC='$(CAST_ENC)'	\
 		RC4_ENC='$(RC4_ENC)' RC5_ENC='$(RC5_ENC)'	\
+		ENGDIRS='$(ENGDIRS)'    \
 		SHA1_ASM_OBJ='$(SHA1_ASM_OBJ)'			\
 		MD5_ASM_OBJ='$(MD5_ASM_OBJ)'			\
 		RMD160_ASM_OBJ='$(RMD160_ASM_OBJ)'		\
diff --git a/crypto/include/internal/cryptlib_int.h b/crypto/include/internal/cryptlib_int.h
index 0e45762..ae30842 100644
--- a/crypto/include/internal/cryptlib_int.h
+++ b/crypto/include/internal/cryptlib_int.h
@@ -70,7 +70,7 @@ int ossl_init_thread_start(uint64_t opts);
  * are those ommitted from crypto.h because they are "reserverd for internal
  * use".
  */
-# define OPENSSL_INIT_ZLIB                   0x010000
+# define OPENSSL_INIT_ZLIB                   0x00010000L
 
 /* OPENSSL_INIT_THREAD flags */
 # define OPENSSL_INIT_THREAD_ASYNC           0x01
diff --git a/crypto/include/internal/engine.h b/crypto/include/internal/engine.h
index 4b70e55..abdb8cc 100644
--- a/crypto/include/internal/engine.h
+++ b/crypto/include/internal/engine.h
@@ -61,3 +61,4 @@ void engine_load_dynamic_internal(void);
 void engine_load_padlock_internal(void);
 void engine_load_capi_internal(void);
 void engine_load_dasync_internal(void);
+void engine_load_afalg_internal(void);
diff --git a/crypto/init.c b/crypto/init.c
index 613606e..2c0bde6 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -470,6 +470,18 @@ static void ossl_init_engine_dasync(void)
     engine_load_dasync_internal();
     engine_inited = 1;
 }
+#  if !defined(OPENSSL_NO_AFALGENG)
+static OPENSSL_INIT_ONCE engine_afalg = OPENSSL_INIT_ONCE_STATIC_INIT;
+static void ossl_init_engine_afalg(void)
+{
+#   ifdef OPENSSL_INIT_DEBUG
+    fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_afalg: "
+                    "engine_load_afalg_internal()\n");
+#   endif
+    engine_load_afalg_internal();
+    engine_inited = 1;
+}
+#  endif
 # endif
 #endif
 
@@ -718,9 +730,15 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
     if (opts & OPENSSL_INIT_ENGINE_DASYNC) {
         ossl_init_once_run(&engine_dasync, ossl_init_engine_dasync);
     }
+#  if !defined(OPENSSL_NO_AFALGENG)
+    if (opts & OPENSSL_INIT_ENGINE_AFALG) {
+        ossl_init_once_run(&engine_afalg, ossl_init_engine_afalg);
+    }
+#  endif
 # endif
     if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN
-                | OPENSSL_INIT_ENGINE_DASYNC | OPENSSL_INIT_ENGINE_OPENSSL)) {
+                | OPENSSL_INIT_ENGINE_DASYNC | OPENSSL_INIT_ENGINE_OPENSSL
+                | OPENSSL_INIT_ENGINE_AFALG)) {
         ENGINE_register_all_complete();
     }
 #endif
diff --git a/engines/Makefile.in b/engines/Makefile.in
index cfe550f..1645ad5 100644
--- a/engines/Makefile.in
+++ b/engines/Makefile.in
@@ -10,6 +10,11 @@ CFLAG=-g
 MAKEFILE=	Makefile
 AR=		ar r
 
+RECURSIVE_MAKE=[ -z "$(ENGDIRS)" ] || for i in $(ENGDIRS) ; do \
+		    (cd $$i && echo "making $$target in $(DIR)/$$i..." && \
+		    $(MAKE) -e TOP=../.. DIR=$$i $$target ) || exit 1; \
+		done;
+
 PADLOCK_ASM_OBJ=
 
 PLIB_LDFLAG=
@@ -49,7 +54,7 @@ ALL=	$(GENERAL) $(SRC) $(HEADER)
 top:
 	(cd ..; $(MAKE) DIRS=$(DIR) all)
 
-all:	lib
+all:	lib subdirs
 
 lib:	$(LIBOBJ) $(TESTLIBOBJ)
 	@if [ "$(DYNAMIC_ENGINES)" = 1 ]; then \
@@ -71,8 +76,12 @@ e_padlock-x86.s:	asm/e_padlock-x86.pl
 e_padlock-x86_64.s:	asm/e_padlock-x86_64.pl
 	$(PERL) asm/e_padlock-x86_64.pl $(PERLASM_SCHEME) > $@
 
+subdirs:
+	@target=all; $(RECURSIVE_MAKE)
+
 files:
 	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+	@target=files; $(RECURSIVE_MAKE)
 
 install:
 	@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
@@ -85,6 +94,7 @@ install:
 			mv -f $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines/$${l}$(DSO_EXT).new $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines/$${l}$(DSO_EXT); \
 		done; \
 	fi
+	@target=install; $(RECURSIVE_MAKE)
 
 uninstall:
 	@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
@@ -94,6 +104,7 @@ uninstall:
 			$(RM) $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines/$${l}$(DSO_EXT); \
 		done; \
 	fi
+	@target=install; $(RECURSIVE_MAKE)
 
 errors:
 	set -e; for l in $(LIBNAMES); do \
@@ -107,5 +118,6 @@ depend:
 
 clean:
 	rm -f *.s *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff
+	@target=clean; $(RECURSIVE_MAKE)
 
 # DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/engines/afalg/Makefile.in b/engines/afalg/Makefile.in
new file mode 100644
index 0000000..fb41993
--- /dev/null
+++ b/engines/afalg/Makefile.in
@@ -0,0 +1,78 @@
+#
+# OpenSSL/engines/afalg/Makefile
+#
+
+DIR=	afalg
+TOP=	../..
+CC=	cc
+INCLUDES= -I../../include
+CFLAG=-g
+MAKEFILE=	Makefile
+AR=		ar r
+
+CFLAGS= $(INCLUDES) $(CFLAG) $(SHARED_CFLAG)
+LIB=$(TOP)/libcrypto.a
+
+LIBNAME=afalg
+LIBSRC=	e_afalg.c
+LIBOBJ=	e_afalg.o e_afalg_err.o
+
+SRC= $(LIBSRC)
+
+top:
+	(cd $(TOP); $(MAKE) DIRS=engines sub_all)
+
+all: errors lib
+
+errors:
+	$(PERL) $(TOP)/util/mkerr.pl -conf e_afalg.ec -nostatic -write $(SRC)
+
+lib: $(LIBOBJ)
+	@if [ "$(DYNAMIC_ENGINES)" = 1 ]; then \
+		$(MAKE) -f $(TOP)/Makefile.shared -e \
+			LIBNAME=$(LIBNAME) \
+			LIBEXTRAS='$(LIBOBJ)' \
+			LIBDEPS='-L$(TOP) -lcrypto' \
+			link_dso.$(SHLIB_TARGET); \
+	else \
+		$(AR) $(LIB) $(LIBOBJ); \
+	fi
+	@touch lib
+
+install:
+	@[ -n "$(INSTALLTOP)" ] # should be set by top Makefile...
+	@if [ -n "$(SHARED_LIBS)" ]; then \
+		set -e; \
+		$(PERL) $(TOP)/util/mkdir-p.pl $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines; \
+		cp $(LIBNAME)$(DSO_EXT) $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines/$(LIBNAME)$(DSO_EXT).new; \
+		chmod 555 $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines/$(LIBNAME)$(DSO_EXT).new; \
+		mv -f $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines/$(LIBNAME)$(DSO_EXT).new $(DESTDIR)$(INSTALLTOP)/$(LIBDIR)/engines/$(LIBNAME)$(DSO_EXT); \
+	fi
+
+
+depend:
+	@[ -z "$(THIS)" ] || $(TOP)/util/domd $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC) $(TESTLIBSRC)
+
+files:
+	$(PERL) $(TOP)/util/files.pl Makefile >> $(TOP)/MINFO
+
+clean:
+	rm -f *.s *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff *.so *.dll *.dylib
+
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+e_afalg.o: e_afalg.c ../../include/openssl/engine.h \
+ ../../include/openssl/opensslconf.h ../../include/openssl/bn.h \
+ ../../include/openssl/e_os2.h ../../include/openssl/ossl_typ.h \
+ ../../include/openssl/crypto.h ../../include/openssl/stack.h \
+ ../../include/openssl/safestack.h ../../include/openssl/opensslv.h \
+ ../../include/openssl/symhacks.h ../../include/openssl/rsa.h \
+ ../../include/openssl/asn1.h ../../include/openssl/bio.h \
+ ../../include/openssl/dsa.h ../../include/openssl/dh.h \
+ ../../include/openssl/ec.h ../../include/openssl/rand.h \
+ ../../include/openssl/ui.h ../../include/openssl/err.h \
+ ../../include/openssl/lhash.h ../../include/openssl/x509.h \
+ ../../include/openssl/buffer.h ../../include/openssl/evp.h \
+ ../../include/openssl/objects.h ../../include/openssl/obj_mac.h \
+ ../../include/openssl/sha.h ../../include/openssl/x509_vfy.h \
+ ../../include/openssl/pkcs7.h ../../include/openssl/async.h e_afalg.h \
+ e_afalg_err.h
diff --git a/engines/afalg/build.info b/engines/afalg/build.info
new file mode 100644
index 0000000..763b35f
--- /dev/null
+++ b/engines/afalg/build.info
@@ -0,0 +1,13 @@
+{- use File::Spec::Functions qw/:DEFAULT rel2abs/; -}
+
+IF[{- !$disabled{afalg} -}]
+ IF[{- $disabled{"dynamic-engine"} -}]
+  LIBS=../../libcrypto
+  SOURCE[../../libcrypto]=e_afalg.c e_afalg_err.c
+ ELSE
+  ENGINES=afalg
+  SOURCE[afalg]=e_afalg.c e_afalg_err.c
+  DEPEND[afalg]=../../libcrypto
+  INCLUDE[afalg]= {- rel2abs(catdir($builddir,"../include")) -} ../../include
+ ENDIF
+ENDIF
diff --git a/engines/afalg/e_afalg.c b/engines/afalg/e_afalg.c
new file mode 100644
index 0000000..d4b4f6b
--- /dev/null
+++ b/engines/afalg/e_afalg.c
@@ -0,0 +1,850 @@
+/* ====================================================================
+ * Copyright (c) 1999-2016 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 at 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 at cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh at cryptsoft.com).
+ *
+ */
+
+/* Required for vmsplice */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/engine.h>
+#include <openssl/async.h>
+
+#include <linux/version.h>
+#define K_MAJ   4
+#define K_MIN1  1
+#define K_MIN2  0
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2)
+# warning "AFALG ENGINE requires Kernel Headers >= 4.1.0"
+# warning "Skipping Compilation of AFALG engine"
+#else
+
+# include <linux/if_alg.h>
+# include <sys/socket.h>
+# include <fcntl.h>
+# include <sys/utsname.h>
+
+# include <linux/aio_abi.h>
+# include <sys/syscall.h>
+# include <errno.h>
+
+# include "e_afalg.h"
+
+# define AFALG_LIB_NAME "AFALG"
+# include "e_afalg_err.h"
+
+# ifndef SOL_ALG
+#  define SOL_ALG 279
+# endif
+
+# ifdef ALG_ZERO_COPY
+#  ifndef SPLICE_F_GIFT
+#   define SPLICE_F_GIFT    (0x08)
+#  endif
+# endif
+
+# define ALG_AES_IV_LEN 16
+# define ALG_IV_LEN(len) (sizeof(struct af_alg_iv) + (len))
+# define ALG_OP_TYPE     unsigned int
+# define ALG_OP_LEN      (sizeof(ALG_OP_TYPE))
+
+#define ALG_MAX_SALG_NAME       64
+#define ALG_MAX_SALG_TYPE       14
+
+# ifdef OPENSSL_NO_DYNAMIC_ENGINE
+void engine_load_afalg_internal(void);
+# endif
+
+/* Local Linkage Functions */
+static int afalg_init_aio(afalg_aio *aio);
+static int afalg_fin_cipher_aio(afalg_aio *ptr, int sfd,
+                                unsigned char *buf, size_t len);
+static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
+                                const char *ciphername);
+static int afalg_destroy(ENGINE *e);
+static int afalg_init(ENGINE *e);
+static int afalg_finish(ENGINE *e);
+const EVP_CIPHER *afalg_aes_128_cbc(void);
+static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+                         const int **nids, int nid);
+static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+                             const unsigned char *iv, int enc);
+static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+                           const unsigned char *in, size_t inl);
+static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx);
+static int afalg_chk_platform(void);
+
+/* Engine Id and Name */
+static const char *engine_afalg_id = "afalg";
+static const char *engine_afalg_name = "AFLAG engine support";
+
+static int afalg_cipher_nids[] = {
+    NID_aes_128_cbc
+};
+
+static EVP_CIPHER *_hidden_aes_128_cbc = NULL;
+
+static inline int io_setup(unsigned n, aio_context_t *ctx)
+{
+    return syscall(__NR_io_setup, n, ctx);
+}
+
+static inline int eventfd(int n)
+{
+    return syscall(__NR_eventfd, n);
+}
+
+static inline int io_destroy(aio_context_t ctx)
+{
+    return syscall(__NR_io_destroy, ctx);
+}
+
+static inline int io_read(aio_context_t ctx, long n, struct iocb **iocb)
+{
+    return syscall(__NR_io_submit, ctx, n, iocb);
+}
+
+static inline int io_getevents(aio_context_t ctx, long min, long max,
+                               struct io_event *events,
+                               struct timespec *timeout)
+{
+    return syscall(__NR_io_getevents, ctx, min, max, events, timeout);
+}
+
+static void afalg_waitfd_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
+                                 OSSL_ASYNC_FD waitfd, void *custom)
+{
+    close(waitfd);
+}
+
+static int afalg_setup_async_event_notification(afalg_aio *aio)
+{
+    ASYNC_JOB *job;
+    ASYNC_WAIT_CTX *waitctx;
+    void *custom = NULL;
+    int ret;
+
+    if ((job = ASYNC_get_current_job()) != NULL) {
+        /* Async mode */
+        waitctx = ASYNC_get_wait_ctx(job);
+        if (waitctx == NULL) {
+            ALG_WARN("%s: ASYNC_get_wait_ctx error", __func__);
+            return 0;
+        }
+        /* Get waitfd from ASYNC_WAIT_CTX if it is alreday set */
+        ret = ASYNC_WAIT_CTX_get_fd(waitctx, engine_afalg_id,
+                                    &aio->efd, &custom);
+        if (ret == 0) {
+            /*
+             * waitfd is not set in ASYNC_WAIT_CTX, create a new one
+             * and set it. efd will be signaled when AIO operation completes
+             */
+            aio->efd = eventfd(0);
+            if (aio->efd == -1) {
+                ALG_PERR("%s: Failed to get eventfd : ", __func__);
+                AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
+                         AFALG_R_EVENTFD_FAILED);
+                return 0;
+            }
+            ret = ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_afalg_id,
+                                             aio->efd, custom,
+                                             afalg_waitfd_cleanup);
+            if (ret == 0) {
+                ALG_WARN("%s: Failed to set wait fd", __func__);
+                close(aio->efd);
+                return 0;
+            }
+            /* make fd non-blocking in async mode */
+            if (fcntl(aio->efd, F_SETFL, O_NONBLOCK) != 0) {
+                ALG_WARN("%s: Failed to set event fd as NONBLOCKING",
+                         __func__);
+            }
+        }
+        aio->mode = MODE_ASYNC;
+    } else {
+        /* Sync mode */
+        aio->efd = eventfd(0);
+        if (aio->efd == -1) {
+            ALG_PERR("%s: Failed to get eventfd : ", __func__);
+            AFALGerr(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION,
+                     AFALG_R_EVENTFD_FAILED);
+            return 0;
+        }
+        aio->mode = MODE_SYNC;
+    }
+    return 1;
+}
+
+int afalg_init_aio(afalg_aio *aio)
+{
+    int r = -1;
+
+    /* Initialise for AIO */
+    aio->aio_ctx = 0;
+    r = io_setup(MAX_INFLIGHTS, &aio->aio_ctx);
+    if (r < 0) {
+        ALG_PERR("%s: io_setup error : ", __func__);
+        AFALGerr(AFALG_F_AFALG_INIT_AIO, AFALG_R_IO_SETUP_FAILED);
+        return 0;
+    }
+
+    memset(aio->cbt, 0, sizeof(aio->cbt));
+    aio->efd = -1;
+    aio->mode = MODE_UNINIT;
+
+    return 1;
+}
+
+int afalg_fin_cipher_aio(afalg_aio *aio, int sfd, unsigned char *buf,
+                         size_t len)
+{
+    int r;
+    int retry = 0;
+    unsigned int done = 0;
+    struct iocb *cb;
+    struct timespec timeout;
+    struct io_event events[MAX_INFLIGHTS];
+    u_int64_t eval = 0;
+
+    timeout.tv_sec = 0;
+    timeout.tv_nsec = 0;
+
+    /* if efd has not been initialised yet do it here */
+    if (aio->mode == MODE_UNINIT) {
+        r = afalg_setup_async_event_notification(aio);
+        if (r == 0)
+            return 0;
+    }
+
+    cb = &(aio->cbt[0 % MAX_INFLIGHTS]);
+    memset(cb, '\0', sizeof(*cb));
+    cb->aio_fildes = sfd;
+    cb->aio_lio_opcode = IOCB_CMD_PREAD;
+    cb->aio_buf = (unsigned long)buf;
+    cb->aio_offset = 0;
+    cb->aio_data = 0;
+    cb->aio_nbytes = len;
+    cb->aio_flags = IOCB_FLAG_RESFD;
+    cb->aio_resfd = aio->efd;
+
+    /*
+     * Perform AIO read on AFALG socket, this in turn performs an async
+     * crypto operation in kernel space
+     */
+    r = io_read(aio->aio_ctx, 1, &cb);
+    if (r < 0) {
+        ALG_PWARN("%s: io_read failed : ", __func__);
+        return 0;
+    }
+
+    do {
+        /* While AIO read is being performed pause job */
+        ASYNC_pause_job();
+
+        /* Check for completion of AIO read */
+        r = read(aio->efd, &eval, sizeof(eval));
+        if (r < 0) {
+            if (errno == EAGAIN || errno == EWOULDBLOCK)
+                continue;
+            ALG_PERR("%s: read failed for event fd : ", __func__);
+            return 0;
+        } else if (r == 0 || eval <= 0) {
+            ALG_WARN("%s: eventfd read %d bytes, eval = %lu\n", __func__, r,
+                     eval);
+        }
+        if (eval > 0) {
+
+            /* Get results of AIO read */
+            r = io_getevents(aio->aio_ctx, 1, MAX_INFLIGHTS,
+                             events, &timeout);
+            if (r > 0) {
+                /*
+                 * events.res indicates the actual status of the operation.
+                 * Handle the error condition first.
+                 */
+                if (events[0].res < 0) {
+                    /*
+                     * Underlying operation cannot be completed at the time
+                     * of previous submission. Resubmit for the operation.
+                     */
+                    if (events[0].res == -EBUSY && retry++ < 3) {
+                        r = io_read(aio->aio_ctx, 1, &cb);
+                        if (r < 0) {
+                            ALG_PERR("%s: retry %d for io_read failed : ",
+                                     __func__, retry);
+                            return 0;
+                        }
+                        continue;
+                    } else {
+                        /*
+                         * Retries exceed for -EBUSY or unrecoverable error
+                         * condition for this instance of operation.
+                         */
+                        ALG_WARN
+                            ("%s: Crypto Operation failed with code %lld\n",
+                             __func__, events[0].res);
+                        return 0;
+                    }
+                }
+                /* Operation successful. */
+                done = 1;
+            } else if (r < 0) {
+                ALG_PERR("%s: io_getevents failed : ", __func__);
+                return 0;
+            } else {
+                ALG_WARN("%s: io_geteventd read 0 bytes\n", __func__);
+            }
+        }
+    } while (!done);
+
+    return 1;
+}
+
+static inline void afalg_set_op_sk(struct cmsghdr *cmsg,
+                                   const unsigned int op)
+{
+    cmsg->cmsg_level = SOL_ALG;
+    cmsg->cmsg_type = ALG_SET_OP;
+    cmsg->cmsg_len = CMSG_LEN(ALG_OP_LEN);
+    *CMSG_DATA(cmsg) = (char)op;
+}
+
+static void afalg_set_iv_sk(struct cmsghdr *cmsg, const unsigned char *iv,
+                            const unsigned int len)
+{
+    struct af_alg_iv *aiv;
+
+    cmsg->cmsg_level = SOL_ALG;
+    cmsg->cmsg_type = ALG_SET_IV;
+    cmsg->cmsg_len = CMSG_LEN(ALG_IV_LEN(len));
+    aiv = (struct af_alg_iv *)CMSG_DATA(cmsg);
+    aiv->ivlen = len;
+    memcpy(aiv->iv, iv, len);
+}
+
+static inline int afalg_set_key(afalg_ctx *actx, const unsigned char *key,
+                                const int klen)
+{
+    int ret;
+    ret = setsockopt(actx->bfd, SOL_ALG, ALG_SET_KEY, key, klen);
+    if (ret < 0) {
+        ALG_PERR("%s: Failed to set socket option : ", __func__);
+        AFALGerr(AFALG_F_AFALG_SET_KEY, AFALG_R_SOCKET_SET_KEY_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+static int afalg_create_sk(afalg_ctx *actx, const char *ciphertype,
+                                const char *ciphername)
+{
+    struct sockaddr_alg sa;
+
+    actx->bfd = actx->sfd = -1;
+    int r = -1;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.salg_family = AF_ALG;
+    strncpy((char *) sa.salg_type, ciphertype, ALG_MAX_SALG_TYPE);
+    sa.salg_type[ALG_MAX_SALG_TYPE-1] = '\0';
+    strncpy((char *) sa.salg_name, ciphername, ALG_MAX_SALG_NAME);
+    sa.salg_name[ALG_MAX_SALG_NAME-1] = '\0';
+
+    actx->bfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
+    if (actx->bfd == -1) {
+        ALG_PERR("%s: Failed to open socket : ", __func__);
+        AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_CREATE_FAILED);
+        goto err;
+    }
+
+    r = bind(actx->bfd, (struct sockaddr *)&sa, sizeof(sa));
+    if (r < 0) {
+        ALG_PERR("%s: Failed to bind socket : ", __func__);
+        AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_BIND_FAILED);
+        goto err;
+    }
+
+    actx->sfd = accept(actx->bfd, NULL, 0);
+    if (actx->sfd < 0) {
+        ALG_PERR("%s: Socket Accept Failed : ", __func__);
+        AFALGerr(AFALG_F_AFALG_CREATE_SK, AFALG_R_SOCKET_ACCEPT_FAILED);
+        goto err;
+    }
+
+    return 1;
+
+ err:
+    if (actx->bfd >= 0)
+        close(actx->bfd);
+    if (actx->sfd >= 0)
+        close(actx->sfd);
+    actx->bfd = actx->sfd = -1;
+    return 0;
+}
+
+static int afalg_start_cipher_sk(afalg_ctx *actx, const unsigned char *in,
+                                 size_t inl, const unsigned char *iv,
+                                 unsigned int enc)
+{
+    struct msghdr msg = { 0 };
+    struct cmsghdr *cmsg;
+    struct iovec iov;
+    ssize_t sbytes;
+# ifdef ALG_ZERO_COPY
+    int ret;
+# endif
+    char cbuf[CMSG_SPACE(ALG_IV_LEN(ALG_AES_IV_LEN)) + CMSG_SPACE(ALG_OP_LEN)];
+
+    memset(cbuf, 0, sizeof(cbuf));
+    msg.msg_control = cbuf;
+    msg.msg_controllen = sizeof(cbuf);
+
+    /*
+     * cipher direction (i.e. encrypt or decrypt) and iv are sent to the
+     * kernel as part of sendmsg()'s ancillary data
+     */
+    cmsg = CMSG_FIRSTHDR(&msg);
+    afalg_set_op_sk(cmsg, enc);
+    cmsg = CMSG_NXTHDR(&msg, cmsg);
+    afalg_set_iv_sk(cmsg, iv, ALG_AES_IV_LEN);
+
+    /* iov that describes input data */
+    iov.iov_base = (unsigned char *)in;
+    iov.iov_len = inl;
+
+    msg.msg_flags = MSG_MORE;
+
+# ifdef ALG_ZERO_COPY
+    /*
+     * ZERO_COPY mode
+     * Works best when buffer is 4k aligned
+     * OPENS: out of place processing (i.e. out != in)
+     */
+
+    /* Input data is not sent as part of call to sendmsg() */
+    msg.msg_iovlen = 0;
+    msg.msg_iov = NULL;
+
+    /* Sendmsg() sends iv and cipher direction to the kernel */
+    sbytes = sendmsg(actx->sfd, &msg, 0);
+    if (sbytes < 0) {
+        ALG_PERR("%s: sendmsg failed for zero copy cipher operation : ",
+                 __func__);
+        return 0;
+    }
+
+    /*
+     * vmsplice and splice are used to pin the user space input buffer for
+     * kernel space processing avoiding copys from user to kernel space
+     */
+    ret = vmsplice(actx->zc_pipe[1], &iov, 1, SPLICE_F_GIFT);
+    if (ret < 0) {
+        ALG_PERR("%s: vmsplice failed : ", __func__);
+        return 0;
+    }
+
+    ret = splice(actx->zc_pipe[0], NULL, actx->sfd, NULL, inl, 0);
+    if (ret < 0) {
+        ALG_PERR("%s: splice failed : ", __func__);
+        return 0;
+    }
+# else
+    msg.msg_iovlen = 1;
+    msg.msg_iov = &iov;
+
+    /* Sendmsg() sends iv, cipher direction and input data to the kernel */
+    sbytes = sendmsg(actx->sfd, &msg, 0);
+    if (sbytes < 0) {
+        ALG_PERR("%s: sendmsg failed for cipher operation : ", __func__);
+        return 0;
+    }
+
+    if (sbytes != (ssize_t) inl) {
+        ALG_WARN("Cipher operation send bytes %zd != inlen %zd\n", sbytes,
+                inl);
+        return 0;
+    }
+# endif
+
+    return 1;
+}
+
+static int afalg_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+                             const unsigned char *iv, int enc)
+{
+    int ciphertype;
+    int ret;
+    afalg_ctx *actx;
+    char ciphername[ALG_MAX_SALG_NAME];
+
+    if (ctx == NULL || key == NULL) {
+        ALG_WARN("%s: Null Parameter\n", __func__);
+        return 0;
+    }
+
+    if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
+        ALG_WARN("%s: Cipher object NULL\n", __func__);
+        return 0;
+    }
+
+    actx = EVP_CIPHER_CTX_cipher_data(ctx);
+    if (actx == NULL) {
+        ALG_WARN("%s: Cipher data NULL\n", __func__);
+        return 0;
+    }
+
+    ciphertype = EVP_CIPHER_CTX_nid(ctx);
+    switch (ciphertype) {
+    case NID_aes_128_cbc:
+        strncpy(ciphername, "cbc(aes)", ALG_MAX_SALG_NAME);
+        break;
+    default:
+        ALG_WARN("%s: Unsupported Cipher type %d\n", __func__, ciphertype);
+        return 0;
+    }
+    ciphername[ALG_MAX_SALG_NAME-1]='\0';
+
+    if (ALG_AES_IV_LEN != EVP_CIPHER_CTX_iv_length(ctx)) {
+        ALG_WARN("%s: Unsupported IV length :%d\n", __func__,
+                EVP_CIPHER_CTX_iv_length(ctx));
+        return 0;
+    }
+
+    /* Setup AFALG socket for crypto processing */
+    ret = afalg_create_sk(actx, "skcipher", ciphername);
+    if (ret < 1)
+        return 0;
+
+
+    ret = afalg_set_key(actx, key, EVP_CIPHER_CTX_key_length(ctx));
+    if (ret < 1)
+        goto err;
+
+    /* Setup AIO ctx to allow async AFALG crypto processing */
+    if (afalg_init_aio(&actx->aio) == 0)
+        goto err;
+
+# ifdef ALG_ZERO_COPY
+    pipe(actx->zc_pipe);
+# endif
+
+    actx->init_done = MAGIC_INIT_NUM;
+
+    return 1;
+
+err:
+    close(actx->sfd);
+    close(actx->bfd);
+    return 0;
+}
+
+static int afalg_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+                           const unsigned char *in, size_t inl)
+{
+    afalg_ctx *actx;
+    int ret;
+    char nxtiv[ALG_AES_IV_LEN] = { 0 };
+
+    if (ctx == NULL || out == NULL || in == NULL) {
+        ALG_WARN("NULL parameter passed to function %s\n", __func__);
+        return 0;
+    }
+
+    actx = (afalg_ctx *) EVP_CIPHER_CTX_cipher_data(ctx);
+    if (actx == NULL || actx->init_done != MAGIC_INIT_NUM) {
+        ALG_WARN("%s afalg ctx passed\n",
+                 ctx == NULL ? "NULL" : "Uninitialised");
+        return 0;
+    }
+
+    /*
+     * set iv now for decrypt operation as the input buffer can be
+     * overwritten for inplace operation where in = out.
+     */
+    if (EVP_CIPHER_CTX_encrypting(ctx) == 0) {
+        memcpy(nxtiv, in + (inl - ALG_AES_IV_LEN), ALG_AES_IV_LEN);
+    }
+
+    /* Send input data to kernel space */
+    ret = afalg_start_cipher_sk(actx, (unsigned char *)in, inl,
+                                EVP_CIPHER_CTX_iv(ctx),
+                                EVP_CIPHER_CTX_encrypting(ctx));
+    if (ret < 1) {
+        return 0;
+    }
+
+    /* Perform async crypto operation in kernel space */
+    ret = afalg_fin_cipher_aio(&actx->aio, actx->sfd, out, inl);
+    if (ret < 1)
+        return 0;
+
+    if (EVP_CIPHER_CTX_encrypting(ctx)) {
+        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), out + (inl - ALG_AES_IV_LEN),
+               ALG_AES_IV_LEN);
+    } else {
+        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), nxtiv, ALG_AES_IV_LEN);
+    }
+
+    return 1;
+}
+
+static int afalg_cipher_cleanup(EVP_CIPHER_CTX *ctx)
+{
+    afalg_ctx *actx;
+
+    if (ctx == NULL) {
+        ALG_WARN("NULL parameter passed to function %s\n", __func__);
+        return 0;
+    }
+
+    actx = (afalg_ctx *) EVP_CIPHER_CTX_cipher_data(ctx);
+    if (actx == NULL || actx->init_done != MAGIC_INIT_NUM) {
+        ALG_WARN("%s afalg ctx passed\n",
+                 ctx == NULL ? "NULL" : "Uninitialised");
+        return 0;
+    }
+
+    close(actx->sfd);
+    close(actx->bfd);
+# ifdef ALG_ZERO_COPY
+    close(actx->zc_pipe[0]);
+    close(actx->zc_pipe[1]);
+# endif
+    /* close efd in sync mode, async mode is closed in afalg_waitfd_cleanup() */
+    if (actx->aio.mode == MODE_SYNC)
+        close(actx->aio.efd);
+    io_destroy(actx->aio.aio_ctx);
+
+    return 1;
+}
+
+const EVP_CIPHER *afalg_aes_128_cbc(void)
+{
+    if (_hidden_aes_128_cbc == NULL
+        && ((_hidden_aes_128_cbc =
+             EVP_CIPHER_meth_new(NID_aes_128_cbc,
+                                 AES_BLOCK_SIZE,
+                                 AES_KEY_SIZE_128)) == NULL
+            || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc, AES_IV_LEN)
+            || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc,
+                                          EVP_CIPH_CBC_MODE |
+                                          EVP_CIPH_FLAG_DEFAULT_ASN1)
+            || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc,
+                                         afalg_cipher_init)
+            || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc,
+                                              afalg_do_cipher)
+            || !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc,
+                                            afalg_cipher_cleanup)
+            || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc,
+                                                  sizeof(afalg_ctx)))) {
+        EVP_CIPHER_meth_free(_hidden_aes_128_cbc);
+        _hidden_aes_128_cbc = NULL;
+    }
+    return _hidden_aes_128_cbc;
+}
+
+static int afalg_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+                         const int **nids, int nid)
+{
+    int r = 1;
+
+    if (cipher == NULL) {
+        *nids = afalg_cipher_nids;
+        return (sizeof(afalg_cipher_nids) / sizeof(afalg_cipher_nids[0]));
+    }
+
+    switch (nid) {
+    case NID_aes_128_cbc:
+        *cipher = afalg_aes_128_cbc();
+        break;
+    default:
+        *cipher = NULL;
+        r = 0;
+    }
+
+    return r;
+}
+
+static int bind_afalg(ENGINE *e)
+{
+    /* Ensure the afalg error handling is set up */
+    ERR_load_AFALG_strings();
+
+    if (!ENGINE_set_id(e, engine_afalg_id)
+        || !ENGINE_set_name(e, engine_afalg_name)
+        || !ENGINE_set_destroy_function(e, afalg_destroy)
+        || !ENGINE_set_init_function(e, afalg_init)
+        || !ENGINE_set_finish_function(e, afalg_finish)) {
+        AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
+        return 0;
+    }
+
+    /*
+     * Create _hidden_aes_128_cbc by calling afalg_aes_128_cbc
+     * now, as bind_aflag can only be called by one thread at a
+     * time.
+     */
+    if (afalg_aes_128_cbc() == NULL) {
+        AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
+        return 0;
+    }
+
+    if (!ENGINE_set_ciphers(e, afalg_ciphers)) {
+        AFALGerr(AFALG_F_BIND_AFALG, AFALG_R_INIT_FAILED);
+        return 0;
+    }
+
+    return 1;
+}
+
+# ifndef OPENSSL_NO_DYNAMIC_ENGINE
+static int bind_helper(ENGINE *e, const char *id)
+{
+    if (id && (strcmp(id, engine_afalg_id) != 0))
+        return 0;
+
+    if (!afalg_chk_platform())
+        return 0;
+
+    if (!bind_afalg(e))
+        return 0;
+    return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN()
+    IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
+# endif
+
+static int afalg_chk_platform(void)
+{
+    int ret;
+    int i;
+    int kver[3] = { -1, -1, -1 };
+    char *str;
+    struct utsname ut;
+
+    ret = uname(&ut);
+    if (ret != 0) {
+        AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
+                 AFALG_R_FAILED_TO_GET_PLATFORM_INFO);
+        return 0;
+    }
+
+    str = strtok(ut.release, ".");
+    for (i = 0; i < 3 && str != NULL; i++) {
+        kver[i] = atoi(str);
+        str = strtok(NULL, ".");
+    }
+
+    if (KERNEL_VERSION(kver[0], kver[1], kver[2])
+        < KERNEL_VERSION(K_MAJ, K_MIN1, K_MIN2)) {
+        ALG_ERR("ASYNC AFALG not supported this kernel(%d.%d.%d)\n",
+                 kver[0], kver[1], kver[2]);
+        ALG_ERR("ASYNC AFALG requires kernel version %d.%d.%d or later\n",
+                 K_MAJ, K_MIN1, K_MIN2);
+        AFALGerr(AFALG_F_AFALG_CHK_PLATFORM,
+                 AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG);
+        return 0;
+    }
+
+    return 1;
+}
+
+# ifdef OPENSSL_NO_DYNAMIC_ENGINE
+static ENGINE *engine_afalg(void)
+{
+    ENGINE *ret = ENGINE_new();
+    if (ret == NULL)
+        return NULL;
+    if (!bind_afalg(ret)) {
+        ENGINE_free(ret);
+        return NULL;
+    }
+    return ret;
+}
+
+void engine_load_afalg_internal(void)
+{
+    ENGINE *toadd;
+
+    if (!afalg_chk_platform())
+        return;
+
+    toadd = engine_afalg();
+    if (toadd == NULL)
+        return;
+    ENGINE_add(toadd);
+    ENGINE_free(toadd);
+    ERR_clear_error();
+}
+# endif
+
+static int afalg_init(ENGINE *e)
+{
+    return 1;
+}
+
+static int afalg_finish(ENGINE *e)
+{
+    return 1;
+}
+
+static int afalg_destroy(ENGINE *e)
+{
+    ERR_unload_AFALG_strings();
+    return 1;
+}
+
+#endif                          /* KERNEL VERSION */
diff --git a/engines/afalg/e_afalg.ec b/engines/afalg/e_afalg.ec
new file mode 100644
index 0000000..2d14d65
--- /dev/null
+++ b/engines/afalg/e_afalg.ec
@@ -0,0 +1 @@
+L       AFALG    e_afalg_err.h e_afalg_err.c
diff --git a/crypto/kdf/kdf_err.c b/engines/afalg/e_afalg.h
similarity index 63%
copy from crypto/kdf/kdf_err.c
copy to engines/afalg/e_afalg.h
index b0321c5..8b589e4 100644
--- a/crypto/kdf/kdf_err.c
+++ b/engines/afalg/e_afalg.h
@@ -52,44 +52,69 @@
  *
  */
 
-/*
- * NOTE: this file was auto generated by the mkerr.pl script: any changes
- * made to it will be overwritten when the script next updates this file,
- * only reason strings will be preserved.
- */
+#ifndef _E_AFALG_H_
+# define _E_AFALG_H_
 
-#include <stdio.h>
-#include <openssl/err.h>
-#include <openssl/kdf.h>
+# ifdef ALG_DEBUG
+#  define ALG_DGB(x, ...) fprintf(stderr, "ALG_DBG: " x, __VA_ARGS__)
+#  define ALG_INFO(x, ...) fprintf(stderr, "ALG_INFO: " x, __VA_ARGS__)
+#  define ALG_WARN(x, ...) fprintf(stderr, "ALG_WARN: " x, __VA_ARGS__)
+# else
+#  define ALG_DGB(x, ...)
+#  define ALG_INFO(x, ...)
+#  define ALG_WARN(x, ...)
+# endif
 
-/* BEGIN ERROR CODES */
-#ifndef OPENSSL_NO_ERR
+# define ALG_ERR(x, ...) fprintf(stderr, "ALG_ERR: " x, __VA_ARGS__)
+# define ALG_PERR(x, ...) \
+                do { \
+                    fprintf(stderr, "ALG_PERR: " x, __VA_ARGS__); \
+                    perror(NULL); \
+                } while(0)
+# define ALG_PWARN(x, ...) \
+                do { \
+                    fprintf(stderr, "ALG_PERR: " x, __VA_ARGS__); \
+                    perror(NULL); \
+                } while(0)
 
-# define ERR_FUNC(func) ERR_PACK(ERR_LIB_KDF,func,0)
-# define ERR_REASON(reason) ERR_PACK(ERR_LIB_KDF,0,reason)
+# ifndef AES_BLOCK_SIZE
+#  define AES_BLOCK_SIZE   16
+# endif
+# define AES_KEY_SIZE_128 16
+# define AES_IV_LEN       16
 
-static ERR_STRING_DATA KDF_str_functs[] = {
-    {ERR_FUNC(KDF_F_PKEY_TLS1_PRF_CTRL_STR), "pkey_tls1_prf_ctrl_str"},
-    {ERR_FUNC(KDF_F_PKEY_TLS1_PRF_DERIVE), "pkey_tls1_prf_derive"},
-    {0, NULL}
-};
+# define MAX_INFLIGHTS 1
+
+typedef enum {
+    MODE_UNINIT = 0,
+    MODE_SYNC,
+    MODE_ASYNC
+} op_mode;
 
-static ERR_STRING_DATA KDF_str_reasons[] = {
-    {ERR_REASON(KDF_R_INVALID_DIGEST), "invalid digest"},
-    {ERR_REASON(KDF_R_MISSING_PARAMETER), "missing parameter"},
-    {ERR_REASON(KDF_R_VALUE_MISSING), "value missing"},
-    {0, NULL}
+struct afalg_aio_st {
+    int efd;
+    op_mode mode;
+    aio_context_t aio_ctx;
+    struct io_event events[MAX_INFLIGHTS];
+    struct iocb cbt[MAX_INFLIGHTS];
 };
+typedef struct afalg_aio_st afalg_aio;
 
-#endif
+/*
+ * MAGIC Number to identify correct initialisation
+ * of afalg_ctx.
+ */
+# define MAGIC_INIT_NUM 0x1890671
 
-void ERR_load_KDF_strings(void)
-{
-#ifndef OPENSSL_NO_ERR
+struct afalg_ctx_st {
+    int init_done;
+    int sfd;
+    int bfd;
+# ifdef ALG_ZERO_COPY
+    int zc_pipe[2];
+# endif
+    afalg_aio aio;
+};
 
-    if (ERR_func_error_string(KDF_str_functs[0].error) == NULL) {
-        ERR_load_strings(0, KDF_str_functs);
-        ERR_load_strings(0, KDF_str_reasons);
-    }
+typedef struct afalg_ctx_st afalg_ctx;
 #endif
-}
diff --git a/engines/e_chil_err.c b/engines/afalg/e_afalg_err.c
similarity index 51%
copy from engines/e_chil_err.c
copy to engines/afalg/e_afalg_err.c
index 2cfcab2..71c4a01 100644
--- a/engines/e_chil_err.c
+++ b/engines/afalg/e_afalg_err.c
@@ -1,5 +1,5 @@
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1999-2016 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
@@ -60,7 +60,7 @@
 
 #include <stdio.h>
 #include <openssl/err.h>
-#include "e_chil_err.h"
+#include "e_afalg_err.h"
 
 /* BEGIN ERROR CODES */
 #ifndef OPENSSL_NO_ERR
@@ -68,89 +68,89 @@
 # define ERR_FUNC(func) ERR_PACK(0,func,0)
 # define ERR_REASON(reason) ERR_PACK(0,0,reason)
 
-static ERR_STRING_DATA HWCRHK_str_functs[] = {
-    {ERR_FUNC(HWCRHK_F_HWCRHK_CTRL), "HWCRHK_CTRL"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_FINISH), "HWCRHK_FINISH"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_GET_PASS), "HWCRHK_GET_PASS"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_INIT), "HWCRHK_INIT"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_INSERT_CARD), "HWCRHK_INSERT_CARD"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_LOAD_PRIVKEY), "HWCRHK_LOAD_PRIVKEY"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_LOAD_PUBKEY), "HWCRHK_LOAD_PUBKEY"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_MOD_EXP), "HWCRHK_MOD_EXP"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_RAND_BYTES), "HWCRHK_RAND_BYTES"},
-    {ERR_FUNC(HWCRHK_F_HWCRHK_RSA_MOD_EXP), "HWCRHK_RSA_MOD_EXP"},
+static ERR_STRING_DATA AFALG_str_functs[] = {
+    {ERR_FUNC(AFALG_F_AFALG_CHK_PLATFORM), "afalg_chk_platform"},
+    {ERR_FUNC(AFALG_F_AFALG_CREATE_BIND_SK), "afalg_create_bind_sk"},
+    {ERR_FUNC(AFALG_F_AFALG_CREATE_BIND_SOCKET), "afalg_create_bind_sk"},
+    {ERR_FUNC(AFALG_F_AFALG_CREATE_SK), "afalg_create_sk"},
+    {ERR_FUNC(AFALG_F_AFALG_INIT_AIO), "afalg_init_aio"},
+    {ERR_FUNC(AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION),
+     "afalg_setup_async_event_notification"},
+    {ERR_FUNC(AFALG_F_AFALG_SET_KEY), "afalg_set_key"},
+    {ERR_FUNC(AFALG_F_AFALG_SOCKET), "afalg_socket"},
+    {ERR_FUNC(AFALG_F_AFALG_START_CIPHER_SK), "afalg_start_cipher_sk"},
+    {ERR_FUNC(AFALG_F_BIND_AFALG), "bind_afalg"},
     {0, NULL}
 };
 
-static ERR_STRING_DATA HWCRHK_str_reasons[] = {
-    {ERR_REASON(HWCRHK_R_ALREADY_LOADED), "already loaded"},
-    {ERR_REASON(HWCRHK_R_BIO_WAS_FREED), "bio was freed"},
-    {ERR_REASON(HWCRHK_R_CHIL_ERROR), "chil error"},
-    {ERR_REASON(HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED),
-     "ctrl command not implemented"},
-    {ERR_REASON(HWCRHK_R_DSO_FAILURE), "dso failure"},
-    {ERR_REASON(HWCRHK_R_MISSING_KEY_COMPONENTS), "missing key components"},
-    {ERR_REASON(HWCRHK_R_NOT_INITIALISED), "not initialised"},
-    {ERR_REASON(HWCRHK_R_NOT_LOADED), "not loaded"},
-    {ERR_REASON(HWCRHK_R_NO_CALLBACK), "no callback"},
-    {ERR_REASON(HWCRHK_R_NO_KEY), "no key"},
-    {ERR_REASON(HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED),
-     "private key algorithms disabled"},
-    {ERR_REASON(HWCRHK_R_REQUEST_FAILED), "request failed"},
-    {ERR_REASON(HWCRHK_R_REQUEST_FALLBACK), "request fallback"},
-    {ERR_REASON(HWCRHK_R_UNIT_FAILURE), "unit failure"},
+static ERR_STRING_DATA AFALG_str_reasons[] = {
+    {ERR_REASON(AFALG_R_EVENTFD_FAILED), "eventfd failed"},
+    {ERR_REASON(AFALG_R_FAILED_TO_GET_PLATFORM_INFO),
+     "failed to get platform info"},
+    {ERR_REASON(AFALG_R_INIT_FAILED), "init failed"},
+    {ERR_REASON(AFALG_R_IO_SETUP_FAILED), "io setup failed"},
+    {ERR_REASON(AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG),
+     "kernel does not support afalg"},
+    {ERR_REASON(AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG),
+     "kernel does not support async afalg"},
+    {ERR_REASON(AFALG_R_MEM_ALLOC_FAILED), "mem alloc failed"},
+    {ERR_REASON(AFALG_R_SOCKET_ACCEPT_FAILED), "socket accept failed"},
+    {ERR_REASON(AFALG_R_SOCKET_BIND_FAILED), "socket bind failed"},
+    {ERR_REASON(AFALG_R_SOCKET_CREATE_FAILED), "socket create failed"},
+    {ERR_REASON(AFALG_R_SOCKET_OPERATION_FAILED), "socket operation failed"},
+    {ERR_REASON(AFALG_R_SOCKET_SET_KEY_FAILED), "socket set key failed"},
     {0, NULL}
 };
 
 #endif
 
-#ifdef HWCRHK_LIB_NAME
-static ERR_STRING_DATA HWCRHK_lib_name[] = {
-    {0, HWCRHK_LIB_NAME},
+#ifdef AFALG_LIB_NAME
+static ERR_STRING_DATA AFALG_lib_name[] = {
+    {0, AFALG_LIB_NAME},
     {0, NULL}
 };
 #endif
 
-static int HWCRHK_lib_error_code = 0;
-static int HWCRHK_error_init = 1;
+static int AFALG_lib_error_code = 0;
+static int AFALG_error_init = 1;
 
-static void ERR_load_HWCRHK_strings(void)
+void ERR_load_AFALG_strings(void)
 {
-    if (HWCRHK_lib_error_code == 0)
-        HWCRHK_lib_error_code = ERR_get_next_error_library();
+    if (AFALG_lib_error_code == 0)
+        AFALG_lib_error_code = ERR_get_next_error_library();
 
-    if (HWCRHK_error_init) {
-        HWCRHK_error_init = 0;
+    if (AFALG_error_init) {
+        AFALG_error_init = 0;
 #ifndef OPENSSL_NO_ERR
-        ERR_load_strings(HWCRHK_lib_error_code, HWCRHK_str_functs);
-        ERR_load_strings(HWCRHK_lib_error_code, HWCRHK_str_reasons);
+        ERR_load_strings(AFALG_lib_error_code, AFALG_str_functs);
+        ERR_load_strings(AFALG_lib_error_code, AFALG_str_reasons);
 #endif
 
-#ifdef HWCRHK_LIB_NAME
-        HWCRHK_lib_name->error = ERR_PACK(HWCRHK_lib_error_code, 0, 0);
-        ERR_load_strings(0, HWCRHK_lib_name);
+#ifdef AFALG_LIB_NAME
+        AFALG_lib_name->error = ERR_PACK(AFALG_lib_error_code, 0, 0);
+        ERR_load_strings(0, AFALG_lib_name);
 #endif
     }
 }
 
-static void ERR_unload_HWCRHK_strings(void)
+void ERR_unload_AFALG_strings(void)
 {
-    if (HWCRHK_error_init == 0) {
+    if (AFALG_error_init == 0) {
 #ifndef OPENSSL_NO_ERR
-        ERR_unload_strings(HWCRHK_lib_error_code, HWCRHK_str_functs);
-        ERR_unload_strings(HWCRHK_lib_error_code, HWCRHK_str_reasons);
+        ERR_unload_strings(AFALG_lib_error_code, AFALG_str_functs);
+        ERR_unload_strings(AFALG_lib_error_code, AFALG_str_reasons);
 #endif
 
-#ifdef HWCRHK_LIB_NAME
-        ERR_unload_strings(0, HWCRHK_lib_name);
+#ifdef AFALG_LIB_NAME
+        ERR_unload_strings(0, AFALG_lib_name);
 #endif
-        HWCRHK_error_init = 1;
+        AFALG_error_init = 1;
     }
 }
 
-static void ERR_HWCRHK_error(int function, int reason, char *file, int line)
+void ERR_AFALG_error(int function, int reason, char *file, int line)
 {
-    if (HWCRHK_lib_error_code == 0)
-        HWCRHK_lib_error_code = ERR_get_next_error_library();
-    ERR_PUT_error(HWCRHK_lib_error_code, function, reason, file, line);
+    if (AFALG_lib_error_code == 0)
+        AFALG_lib_error_code = ERR_get_next_error_library();
+    ERR_PUT_error(AFALG_lib_error_code, function, reason, file, line);
 }
diff --git a/demos/engines/cluster_labs/hw_cluster_labs_err.h b/engines/afalg/e_afalg_err.h
similarity index 62%
copy from demos/engines/cluster_labs/hw_cluster_labs_err.h
copy to engines/afalg/e_afalg_err.h
index e9e58d5..64468c3 100644
--- a/demos/engines/cluster_labs/hw_cluster_labs_err.h
+++ b/engines/afalg/e_afalg_err.h
@@ -1,5 +1,5 @@
 /* ====================================================================
- * Copyright (c) 2001-2002 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 2001-2016 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
@@ -52,47 +52,50 @@
  *
  */
 
-#ifndef HEADER_CL_ERR_H
-# define HEADER_CL_ERR_H
+#ifndef HEADER_AFALG_ERR_H
+# define HEADER_AFALG_ERR_H
 
-#ifdef  __cplusplus
+# ifdef  __cplusplus
 extern "C" {
-#endif
+# endif
 
 /* 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.
  */
-static void ERR_load_CL_strings(void);
-static void ERR_unload_CL_strings(void);
-static void ERR_CL_error(int function, int reason, char *file, int line);
-# define CLerr(f,r) ERR_CL_error((f),(r),OPENSSL_FILE,OPENSSL_LINE)
+void ERR_load_AFALG_strings(void);
+void ERR_unload_AFALG_strings(void);
+void ERR_AFALG_error(int function, int reason, char *file, int line);
+# define AFALGerr(f,r) ERR_AFALG_error((f),(r),__FILE__,__LINE__)
 
-/* Error codes for the CL functions. */
+/* Error codes for the AFALG functions. */
 
 /* Function codes. */
-# define CL_F_CLUSTER_LABS_CTRL                           100
-# define CL_F_CLUSTER_LABS_DSA_SIGN                       101
-# define CL_F_CLUSTER_LABS_DSA_VERIFY                     102
-# define CL_F_CLUSTER_LABS_FINISH                         103
-# define CL_F_CLUSTER_LABS_INIT                           104
-# define CL_F_CLUSTER_LABS_MOD_EXP                        105
-# define CL_F_CLUSTER_LABS_MOD_EXP_CRT                    106
-# define CL_F_CLUSTER_LABS_RAND_BYTES                     107
-# define CL_F_CLUSTER_LABS_RSA_MOD_EXP                    108
-# define CL_F_CLUSTER_LABS_RSA_PRIV_DEC                   109
-# define CL_F_CLUSTER_LABS_RSA_PRIV_ENC                   110
-# define CL_F_CLUSTER_LABS_RSA_PUB_DEC                    111
-# define CL_F_CLUSTER_LABS_RSA_PUB_ENC                    112
+# define AFALG_F_AFALG_CHK_PLATFORM                       100
+# define AFALG_F_AFALG_CREATE_BIND_SK                     106
+# define AFALG_F_AFALG_CREATE_BIND_SOCKET                 105
+# define AFALG_F_AFALG_CREATE_SK                          108
+# define AFALG_F_AFALG_INIT_AIO                           101
+# define AFALG_F_AFALG_SETUP_ASYNC_EVENT_NOTIFICATION     107
+# define AFALG_F_AFALG_SET_KEY                            109
+# define AFALG_F_AFALG_SOCKET                             102
+# define AFALG_F_AFALG_START_CIPHER_SK                    103
+# define AFALG_F_BIND_AFALG                               104
 
 /* Reason codes. */
-# define CL_R_ALREADY_LOADED                              100
-# define CL_R_COMMAND_NOT_IMPLEMENTED                     101
-# define CL_R_DSO_FAILURE                                 102
-# define CL_R_FUNCTION_NOT_BINDED                         103
-# define CL_R_INIT_FAILED                                 104
-# define CL_R_NOT_LOADED                                  105
+# define AFALG_R_EVENTFD_FAILED                           108
+# define AFALG_R_FAILED_TO_GET_PLATFORM_INFO              111
+# define AFALG_R_INIT_FAILED                              100
+# define AFALG_R_IO_SETUP_FAILED                          105
+# define AFALG_R_KERNEL_DOES_NOT_SUPPORT_AFALG            101
+# define AFALG_R_KERNEL_DOES_NOT_SUPPORT_ASYNC_AFALG      107
+# define AFALG_R_MEM_ALLOC_FAILED                         102
+# define AFALG_R_SOCKET_ACCEPT_FAILED                     110
+# define AFALG_R_SOCKET_BIND_FAILED                       103
+# define AFALG_R_SOCKET_CREATE_FAILED                     109
+# define AFALG_R_SOCKET_OPERATION_FAILED                  104
+# define AFALG_R_SOCKET_SET_KEY_FAILED                    106
 
 #ifdef  __cplusplus
 }
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index fb6a2b9..d52c14c 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -547,6 +547,7 @@ int CRYPTO_memcmp(const volatile void * volatile in_a,
 # define OPENSSL_INIT_ENGINE_PADLOCK         0x00004000L
 # define OPENSSL_INIT_ENGINE_DASYNC          0x00008000L
 /* OPENSSL_INIT flag 0x00010000 reserved for internal use */
+# define OPENSSL_INIT_ENGINE_AFALG           0x00020000L
 /* OPENSSL_INIT flag range 0xfff00000 reserved for OPENSSL_init_ssl() */
 /* Max OPENSSL_INIT flag value is 0x80000000 */
 
diff --git a/include/openssl/engine.h b/include/openssl/engine.h
index c1dd45b..7b7b2a1 100644
--- a/include/openssl/engine.h
+++ b/include/openssl/engine.h
@@ -398,6 +398,8 @@ ENGINE *ENGINE_by_id(const char *id);
     OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CAPI, NULL)
 #  define ENGINE_load_dasync() \
     OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_DASYNC, NULL)
+#  define ENGINE_load_afalg() \
+    OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL)
 # endif
 # define ENGINE_load_cryptodev() \
     OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CRYPTODEV, NULL)
diff --git a/test/Makefile.in b/test/Makefile.in
index 7a5dcc1..313ff6f 100644
--- a/test/Makefile.in
+++ b/test/Makefile.in
@@ -83,6 +83,7 @@ ASYNCTEST=	asynctest
 DTLSV1LISTENTEST = dtlsv1listentest
 CTTEST=	ct_test
 THREADSTEST=	threadstest
+AFALGTEST= afalgtest
 
 TESTS=		alltests
 
@@ -104,7 +105,8 @@ EXE=	$(NPTEST)$(EXE_EXT) $(MEMLEAKTEST)$(EXE_EXT) \
 	$(HEARTBEATTEST)$(EXE_EXT) $(P5_CRPT2_TEST)$(EXE_EXT) \
 	$(CONSTTIMETEST)$(EXE_EXT) $(VERIFYEXTRATEST)$(EXE_EXT) \
 	$(CLIENTHELLOTEST)$(EXE_EXT) $(PACKETTEST)$(EXE_EXT) $(ASYNCTEST)$(EXE_EXT) \
-	$(DTLSV1LISTENTEST)$(EXE_EXT) $(CTTEST)$(EXE_EXT) $(THREADSTEST)$(EXE_EXT)
+	$(DTLSV1LISTENTEST)$(EXE_EXT) $(CTTEST)$(EXE_EXT) $(THREADSTEST)$(EXE_EXT) \
+	$(AFALGTEST)$(EXE_EXT)
 
 # $(METHTEST)$(EXE_EXT)
 
@@ -122,7 +124,7 @@ OBJ=	$(NPTEST).o $(MEMLEAKTEST).o \
 	$(HEARTBEATTEST).o $(P5_CRPT2_TEST).o \
 	$(CONSTTIMETEST).o $(VERIFYEXTRATEST).o $(CLIENTHELLOTEST).o \
 	$(PACKETTEST).o $(ASYNCTEST).o $(DTLSV1LISTENTEST).o $(CTTEST).o \
-	$(THREADSTEST).o testutil.o
+	$(THREADSTEST).o testutil.o $(AFALGTEST).o
 
 SRC=	$(NPTEST).c $(MEMLEAKTEST).c \
 	$(BNTEST).c $(ECTEST).c \
@@ -137,7 +139,7 @@ SRC=	$(NPTEST).c $(MEMLEAKTEST).c \
 	$(HEARTBEATTEST).c $(P5_CRPT2_TEST).c \
 	$(CONSTTIMETEST).c $(VERIFYEXTRATEST).c $(CLIENTHELLOTEST).c \
 	$(PACKETTEST).c $(ASYNCTEST).c $(DTLSV1LISTENTEST).c $(CTTEST).c \
-	$(THREADSTEST).c testutil.c
+	$(THREADSTEST).c testutil.c $(AFALGTEST).c
 
 HEADER=	testutil.h
 
@@ -382,4 +384,7 @@ $(THREADSTEST)$(EXE_EXT): $(THREADSTEST).o $(DLIBCRYPTO)
 dummytest$(EXE_EXT): dummytest.o $(DLIBCRYPTO)
 	@target=dummytest; $(BUILD_CMD)
 
+$(AFALGTEST)$(EXE_EXT): $(AFALGTEST).o $(DLIBCRYPTO)
+	@target=$(AFALGTEST); $(BUILD_CMD)
+
 # DO NOT DELETE THIS LINE -- make depend depends on it.
diff --git a/test/memleaktest.c b/test/afalgtest.c
similarity index 53%
copy from test/memleaktest.c
copy to test/afalgtest.c
index f894590..c15e111 100644
--- a/test/memleaktest.c
+++ b/test/afalgtest.c
@@ -1,5 +1,5 @@
 /* ====================================================================
- * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 2016 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
@@ -51,41 +51,101 @@
  * Hudson (tjh at cryptsoft.com).
  *
  */
-
 #include <stdio.h>
+#include <openssl/engine.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
 #include <string.h>
-#include <openssl/bio.h>
-#include <openssl/crypto.h>
+
+#ifndef OPENSSL_NO_AFALGENG
+
+/* Use a buffer size which is not aligned to block size */
+#define BUFFER_SIZE     (8 * 1024) - 13
+
+static int test_afalg_aes_128_cbc(ENGINE *e)
+{
+    EVP_CIPHER_CTX *ctx;
+    const EVP_CIPHER *cipher = EVP_aes_128_cbc();
+    unsigned char key[] = "\x5F\x4D\xCC\x3B\x5A\xA7\x65\xD6\
+                           \x1D\x83\x27\xDE\xB8\x82\xCF\x99";
+    unsigned char iv[] = "\x2B\x95\x99\x0A\x91\x51\x37\x4A\
+                          \xBD\x8F\xF8\xC5\xA7\xA0\xFE\x08";
+
+    unsigned char in[BUFFER_SIZE];
+    unsigned char ebuf[BUFFER_SIZE + 32];
+    unsigned char dbuf[BUFFER_SIZE + 32];
+    int encl, encf, decl, decf;
+    unsigned int status = 0;
+
+    ctx = EVP_CIPHER_CTX_new();
+    if (ctx == NULL) {
+        fprintf(stderr, "%s() failed to allocate ctx\n", __func__);
+        return 0;
+    }
+    EVP_CIPHER_CTX_init(ctx);
+    RAND_bytes(in, BUFFER_SIZE);
+
+    if (       !EVP_CipherInit_ex(ctx, cipher, e, key, iv, 1)
+            || !EVP_CipherUpdate(ctx, ebuf, &encl, in, BUFFER_SIZE)
+            || !EVP_CipherFinal_ex(ctx, ebuf+encl, &encf)) {
+        fprintf(stderr, "%s() failed encryption\n", __func__);
+        goto end;
+    }
+    encl += encf;
+
+    if (       !EVP_CIPHER_CTX_reset(ctx)
+            || !EVP_CipherInit_ex(ctx, cipher, e, key, iv, 0)
+            || !EVP_CipherUpdate(ctx, dbuf, &decl, ebuf, encl)
+            || !EVP_CipherFinal_ex(ctx, dbuf+decl, &decf)) {
+        fprintf(stderr, "%s() failed decryption\n", __func__);
+        goto end;
+    }
+    decl += decf;
+
+    if (       decl != BUFFER_SIZE
+            || memcmp(dbuf, in, BUFFER_SIZE)) {
+        fprintf(stderr, "%s() failed Dec(Enc(P)) != P\n", __func__);
+        goto end;
+    }
+
+    status = 1;
+
+ end:
+    EVP_CIPHER_CTX_free(ctx);
+    return status;
+}
+#endif
 
 int main(int argc, char **argv)
 {
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
-    char *p;
-    char *lost;
-    int noleak;
-
-    p = getenv("OPENSSL_DEBUG_MEMORY");
-    if (p != NULL && strcmp(p, "on") == 0)
-        CRYPTO_set_mem_debug(1);
+#ifdef OPENSSL_NO_AFALGENG
+    fprintf(stderr, "AFALG not supported - skipping AFALG tests\n");
+#else
+
+    ENGINE *e;
+
+    CRYPTO_set_mem_debug(1);
     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
 
-    lost = OPENSSL_malloc(3);
-    if (lost == NULL) {
-        fprintf(stderr, "OPENSSL_malloc failed\n");
+    ENGINE_load_builtin_engines();
+
+# ifndef OPENSSL_NO_STATIC_ENGINE
+    OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_AFALG, NULL);
+# endif
+
+    e = ENGINE_by_id("afalg");
+    if (e == NULL) {
+        fprintf(stderr, "AFALG Test: Failed to load AFALG Engine\n");
         return 1;
     }
 
-    if (argv[1] && strcmp(argv[1], "freeit") == 0) {
-        OPENSSL_free(lost);
-        lost = NULL;
+    if (test_afalg_aes_128_cbc(e) == 0) {
+        ENGINE_free(e);
+        return 1;
     }
 
-    noleak = CRYPTO_mem_leaks_fp(stderr);
-    /* If -1 return value something bad happened */
-    if (noleak == -1)
-        return 1;
-    return ((lost != NULL) ^ (noleak == 0));
-#else
-    return 0;
+    ENGINE_free(e);
 #endif
+    printf("PASS\n");
+    return 0;
 }
diff --git a/test/build.info b/test/build.info
index c2ee234..cd5d8cd 100644
--- a/test/build.info
+++ b/test/build.info
@@ -13,7 +13,7 @@ PROGRAMS=\
         danetest heartbeat_test p5_crpt2_test \
         constant_time_test verify_extra_test clienthellotest \
         packettest asynctest secmemtest srptest memleaktest \
-        dtlsv1listentest ct_test threadstest
+        dtlsv1listentest ct_test threadstest afalgtest
 
 SOURCE[nptest]=nptest.c
 INCLUDE[nptest]={- rel2abs(catdir($builddir,"../include")) -} ../include
@@ -211,4 +211,8 @@ SOURCE[threadstest]=threadstest.c
 INCLUDE[threadstest]={- rel2abs(catdir($builddir,"../include")) -} .. ../include
 DEPEND[threadstest]=../libcrypto
 
+SOURCE[afalgtest]=afalgtest.c
+INCLUDE[afalgtest]={- rel2abs(catdir($builddir,"../include")) -} .. ../include
+DEPEND[afalgtest]=../libcrypto
+
 INCLUDE[testutil.o]=..
diff --git a/test/recipes/90-test_networking.t b/test/recipes/30-test_afalg.t
similarity index 65%
copy from test/recipes/90-test_networking.t
copy to test/recipes/30-test_afalg.t
index 84d616d..f69c902 100644
--- a/test/recipes/90-test_networking.t
+++ b/test/recipes/30-test_afalg.t
@@ -1,7 +1,6 @@
 #!/usr/bin/perl
-# Written by Richard Levitte for the OpenSSL project.
 # ====================================================================
-# Copyright (c) 2015-2016 The OpenSSL Project.  All rights reserved.
+# Copyright (c) 2016 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
@@ -53,59 +52,17 @@
 # Hudson (tjh at cryptsoft.com).
 
 use strict;
-use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_file bldtop_dir/;
+use OpenSSL::Test qw/:DEFAULT bldtop_dir/;
 use OpenSSL::Test::Utils;
-use TLSProxy::Proxy;
 
-my $test_name = "test_networking";
+my $test_name = "test_afalg";
 setup($test_name);
 
-plan skip_all => "TLSProxy isn't usable on $^O"
-    if $^O =~ /^VMS$/;
+plan skip_all => "$test_name not supported for this build"
+    if disabled("engine") || disabled("afalg");
 
-plan skip_all => "$test_name needs the dynamic engine feature enabled"
-    if disabled("engine") || disabled("dynamic-engine");
+plan tests => 1;
 
-$ENV{OPENSSL_ENGINES} = bldtop_dir("engines");
-$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
+$ENV{OPENSSL_ENGINES} = bldtop_dir("engines/afalg");
 
-my $proxy = TLSProxy::Proxy->new(
-    undef,
-    cmdstr(app(["openssl"])),
-    srctop_file("apps", "server.pem"),
-    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
-);
-
-plan tests => 2;
-
-#Test 1: Try IPv4
-$proxy->clear();
-$proxy->serverflags("-4");
-$proxy->clientflags("-4");
-$proxy->server_addr("127.0.0.1");
-$proxy->proxy_addr("127.0.0.1");
-ok(check_connection(), "Trying IPv4");
-
- SKIP: {
-     skip "No IPv6 support", 1 unless $proxy->supports_IPv6();
-
-     #Test 2: Try IPv6
-     $proxy->clear();
-     $proxy->serverflags("-6");
-     $proxy->clientflags("-6");
-     $proxy->server_addr("[::1]");
-     $proxy->proxy_addr("[::1]");
-     ok(check_connection(), "Trying IPv6");
-}
-
-sub check_connection
-{
-    eval { $proxy->start(); };
-
-    if ($@ ne "") {
-	print STDERR "Proxy connection failed: $@\n";
-	return 0;
-    }
-
-    1;
-}
+ok(run(test(["afalgtest"])), "running afalgtest");


More information about the openssl-commits mailing list