diff mbox

[PATCHv3,3/3] Add linux-generic crypto implementation

Message ID 1406649661-614-4-git-send-email-robking@cisco.com
State New
Headers show

Commit Message

Robbie King July 29, 2014, 4:01 p.m. UTC
Signed-off-by: Robbie King <robking@cisco.com>
---
 platform/linux-generic/Makefile.am                 |    2 +
 .../linux-generic/include/odp_crypto_internal.h    |   85 ++++
 platform/linux-generic/odp_crypto.c                |  472 ++++++++++++++++++++
 3 files changed, 559 insertions(+), 0 deletions(-)
 create mode 100644 platform/linux-generic/include/odp_crypto_internal.h
 create mode 100644 platform/linux-generic/odp_crypto.c

Comments

Anders Roxell July 29, 2014, 6:34 p.m. UTC | #1
Hi Robbie,

A nit:
In general, avoid mix having two newlines and one newline between
function definitions, stick with one of them.

On 2014-07-29 12:01, Robbie King wrote:
> Signed-off-by: Robbie King <robking@cisco.com>
> ---

[...]

> +
> +static odp_crypto_global_t *global;
> +
> +/*
> + * TODO: This is a serious hack to allow us to use packet buffer to convey
> + *       crypto operation results by placing them at the very end of the
> + *       packet buffer.
> + */

Just a question, is this suppose to go away in future commits?
Or is this a clever solution that is meant to stay?

Cheers,
Anders
Anders Roxell July 29, 2014, 6:37 p.m. UTC | #2
Hi again Robbie,

On 2014-07-29 12:01, Robbie King wrote:
> Signed-off-by: Robbie King <robking@cisco.com>
> ---
>  platform/linux-generic/Makefile.am                 |    2 +
>  .../linux-generic/include/odp_crypto_internal.h    |   85 ++++
>  platform/linux-generic/odp_crypto.c                |  472 ++++++++++++++++++++

[...]

> +	/*
> +	 * robking: a) the queue is supposed to come from session
> +	 *          b) ordering question asks whether we must
> +	 *             use the packet to return status
> +	 */

A comment for you only right?

Cheers,
Anders
Mike Holmes July 29, 2014, 6:40 p.m. UTC | #3
On 29 July 2014 14:34, Anders Roxell <anders.roxell@linaro.org> wrote:

> Hi Robbie,
>
> A nit:
> In general, avoid mix having two newlines and one newline between
> function definitions, stick with one of them.
>
> On 2014-07-29 12:01, Robbie King wrote:
> > Signed-off-by: Robbie King <robking@cisco.com>
> > ---
>
> [...]
>
> > +
> > +static odp_crypto_global_t *global;
> > +
> > +/*
> > + * TODO: This is a serious hack to allow us to use packet buffer to
> convey
> > + *       crypto operation results by placing them at the very end of the
> > + *       packet buffer.
> > + */
>
>
Nit
Adding todo as
/**
* @todo will bring the information up to the doxygen documentation on the
generated  "todo" page
it is easier to track that todos get done then
But this is not a patch stopper


> Just a question, is this suppose to go away in future commits?
> Or is this a clever solution that is meant to stay?
>
> Cheers,
> Anders
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/lng-odp
>
Robbie King July 29, 2014, 6:42 p.m. UTC | #4
Yes, that should be able to be removed shortly.  The original plan was to get the
code into git repository and then Taras was going to propose the new API that
we have been discussing.  I believe once that is in place the ambiguity of packets
and completion events will be solved and this hack can be removed.

From: Mike Holmes [mailto:mike.holmes@linaro.org]

Sent: Tuesday, July 29, 2014 2:41 PM
To: Anders Roxell
Cc: Robbie King (robking); lng-odp-forward
Subject: Re: [lng-odp] [PATCHv3 3/3] Add linux-generic crypto implementation



On 29 July 2014 14:34, Anders Roxell <anders.roxell@linaro.org<mailto:anders.roxell@linaro.org>> wrote:
Hi Robbie,

A nit:
In general, avoid mix having two newlines and one newline between
function definitions, stick with one of them.

On 2014-07-29 12:01, Robbie King wrote:
> Signed-off-by: Robbie King <robking@cisco.com<mailto:robking@cisco.com>>

> ---

[...]

> +

> +static odp_crypto_global_t *global;

> +

> +/*

> + * TODO: This is a serious hack to allow us to use packet buffer to convey

> + *       crypto operation results by placing them at the very end of the

> + *       packet buffer.

> + */


Nit
Adding todo as
/**
* @todo will bring the information up to the doxygen documentation on the generated  "todo" page
it is easier to track that todos get done then
But this is not a patch stopper

Just a question, is this suppose to go away in future commits?
Or is this a clever solution that is meant to stay?

Cheers,
Anders

_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org<mailto:lng-odp@lists.linaro.org>
http://lists.linaro.org/mailman/listinfo/lng-odp



--
Mike Holmes
Linaro Technical Manager / Lead
LNG - ODP
Robbie King July 29, 2014, 6:47 p.m. UTC | #5
Yep, that needs to come out.

-----Original Message-----
From: Anders Roxell [mailto:anders.roxell@linaro.org] 
Sent: Tuesday, July 29, 2014 2:38 PM
To: Robbie King (robking)
Cc: lng-odp@lists.linaro.org
Subject: Re: [lng-odp] [PATCHv3 3/3] Add linux-generic crypto implementation

Hi again Robbie,

On 2014-07-29 12:01, Robbie King wrote:
> Signed-off-by: Robbie King <robking@cisco.com>
> ---
>  platform/linux-generic/Makefile.am                 |    2 +
>  .../linux-generic/include/odp_crypto_internal.h    |   85 ++++
>  platform/linux-generic/odp_crypto.c                |  472 ++++++++++++++++++++

[...]

> +	/*
> +	 * robking: a) the queue is supposed to come from session
> +	 *          b) ordering question asks whether we must
> +	 *             use the packet to return status
> +	 */

A comment for you only right?

Cheers,
Anders
Anders Roxell July 29, 2014, 6:54 p.m. UTC | #6
On 2014-07-29 18:42, Robbie King (robking) wrote:
> Yes, that should be able to be removed shortly.  The original plan was to get the
> code into git repository and then Taras was going to propose the new API that
> we have been discussing.  I believe once that is in place the ambiguity of packets
> and completion events will be solved and this hack can be removed.

Great, thank you Robbie for the quick reply!

Cheers,
Anders

> 
> From: Mike Holmes [mailto:mike.holmes@linaro.org]
> Sent: Tuesday, July 29, 2014 2:41 PM
> To: Anders Roxell
> Cc: Robbie King (robking); lng-odp-forward
> Subject: Re: [lng-odp] [PATCHv3 3/3] Add linux-generic crypto implementation
> 
> 
> 
> On 29 July 2014 14:34, Anders Roxell <anders.roxell@linaro.org<mailto:anders.roxell@linaro.org>> wrote:
> Hi Robbie,
> 
> A nit:
> In general, avoid mix having two newlines and one newline between
> function definitions, stick with one of them.
> 
> On 2014-07-29 12:01, Robbie King wrote:
> > Signed-off-by: Robbie King <robking@cisco.com<mailto:robking@cisco.com>>
> > ---
> [...]
> 
> > +
> > +static odp_crypto_global_t *global;
> > +
> > +/*
> > + * TODO: This is a serious hack to allow us to use packet buffer to convey
> > + *       crypto operation results by placing them at the very end of the
> > + *       packet buffer.
> > + */
> 
> Nit
> Adding todo as
> /**
> * @todo will bring the information up to the doxygen documentation on the generated  "todo" page
> it is easier to track that todos get done then
> But this is not a patch stopper
> 
> Just a question, is this suppose to go away in future commits?
> Or is this a clever solution that is meant to stay?
> 
> Cheers,
> Anders
> 
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org<mailto:lng-odp@lists.linaro.org>
> http://lists.linaro.org/mailman/listinfo/lng-odp
> 
> 
> 
> --
> Mike Holmes
> Linaro Technical Manager / Lead
> LNG - ODP
diff mbox

Patch

diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index 9be1f4b..1728a19 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -25,6 +25,7 @@  include_HEADERS = \
 		  $(top_srcdir)/include/odp_compiler.h \
 		  $(top_srcdir)/include/odp_config.h \
 		  $(top_srcdir)/include/odp_coremask.h \
+		  $(top_srcdir)/include/odp_crypto.h \
 		  $(top_srcdir)/include/odp_debug.h \
 		  $(top_srcdir)/include/odp_hints.h \
 		  $(top_srcdir)/include/odp_init.h \
@@ -63,6 +64,7 @@  __LIB__libodp_la_SOURCES = \
 			   odp_buffer.c \
 			   odp_buffer_pool.c \
 			   odp_coremask.c \
+			   odp_crypto.c \
 			   odp_init.c \
 			   odp_linux.c \
 			   odp_packet.c \
diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h
new file mode 100644
index 0000000..75b5dd6
--- /dev/null
+++ b/platform/linux-generic/include/odp_crypto_internal.h
@@ -0,0 +1,85 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#ifndef ODP_CRYPTO_INTERNAL_H_
+#define ODP_CRYPTO_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <openssl/des.h>
+
+#define OP_RESULT_MAGIC 0x91919191
+
+/** Forward declaration of session structure */
+typedef struct odp_crypto_generic_session odp_crypto_generic_session_t;
+
+/**
+ * Algorithm handler function prototype
+ */
+typedef
+enum crypto_alg_err (*crypto_func_t)(odp_crypto_op_params_t *params,
+				     odp_crypto_generic_session_t *session);
+
+/**
+ * Per crypto session data structure
+ */
+struct odp_crypto_generic_session {
+	uint32_t index;
+	enum odp_crypto_op op;
+	bool do_cipher_first;
+	odp_queue_t compl_queue;
+	odp_buffer_pool_t output_pool;
+	struct {
+		enum odp_cipher_alg   alg;
+		struct {
+			uint8_t *data;
+			size_t   len;
+		} iv;
+		union {
+			struct {
+				DES_key_schedule ks1;
+				DES_key_schedule ks2;
+				DES_key_schedule ks3;
+			} des;
+		} data;
+		crypto_func_t func;
+	} cipher;
+	struct {
+		enum odp_auth_alg  alg;
+		union {
+			struct {
+				uint8_t key[16];
+			} md5;
+		} data;
+		crypto_func_t func;
+	} auth;
+
+};
+
+/**
+ * Per packet operation result
+ */
+typedef struct odp_crypto_generic_op_result {
+	uint32_t magic;
+	odp_crypto_compl_status_t cipher;
+	odp_crypto_compl_status_t auth;
+} odp_crypto_generic_op_result_t;
+
+/**
+ * Per session creation operation result
+ */
+typedef struct odp_crypto_generic_session_result {
+	enum odp_crypto_ses_create_err rc;
+	odp_crypto_session_t           session;
+} odp_crypto_generic_session_result_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
new file mode 100644
index 0000000..d738665
--- /dev/null
+++ b/platform/linux-generic/odp_crypto.c
@@ -0,0 +1,472 @@ 
+/* Copyright (c) 2014, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_crypto.h>
+#include <odp_internal.h>
+#include <odp_atomic.h>
+#include <odp_spinlock.h>
+#include <odp_sync.h>
+#include <odp_debug.h>
+#include <odp_align.h>
+#include <odp_shared_memory.h>
+#include <odp_crypto_internal.h>
+#include <odp_hints.h>
+#include <helper/odp_packet_helper.h>
+
+#include <string.h>
+
+#include <openssl/des.h>
+#include <openssl/rand.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+
+#define MAX_SESSIONS 32
+
+typedef struct {
+	odp_atomic_u32_t next;
+	uint32_t         max;
+	odp_crypto_generic_session_t sessions[0];
+} odp_crypto_global_t;
+
+static odp_crypto_global_t *global;
+
+/*
+ * TODO: This is a serious hack to allow us to use packet buffer to convey
+ *       crypto operation results by placing them at the very end of the
+ *       packet buffer.
+ */
+static
+odp_crypto_generic_op_result_t *get_op_result_from_buffer(odp_buffer_t buf)
+{
+	uint8_t   *temp;
+	odp_crypto_generic_op_result_t *result;
+
+	temp  = odp_buffer_addr(buf);
+	temp += odp_buffer_size(buf);
+	temp -= sizeof(*result);
+	result = (odp_crypto_generic_op_result_t *)(void *)temp;
+	return result;
+}
+
+static
+odp_crypto_generic_session_t *alloc_session(void)
+{
+	uint32_t idx;
+	odp_crypto_generic_session_t *session = NULL;
+
+	idx = odp_atomic_fetch_inc_u32(&global->next);
+	if (idx < global->max) {
+		session = &global->sessions[idx];
+		session->index = idx;
+	}
+	return session;
+}
+
+static
+enum crypto_alg_err null_crypto_routine(
+	odp_crypto_op_params_t *params ODP_UNUSED,
+	odp_crypto_generic_session_t *session ODP_UNUSED)
+{
+	return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+enum crypto_alg_err md5_gen(odp_crypto_op_params_t *params,
+			    odp_crypto_generic_session_t *session)
+{
+	uint8_t *data  = odp_packet_buf_addr(params->out_pkt);
+	uint8_t *icv   = data;
+	uint32_t len   = params->auth_range.length;
+	uint8_t  hash[EVP_MAX_MD_SIZE];
+	uint32_t hlen = 12;
+
+	/* Adjust pointer for beginning of area to auth */
+	data += params->auth_range.offset;
+	icv  += params->hash_result_offset;
+
+	/* Hash it */
+	HMAC(EVP_md5(),
+	     session->auth.data.md5.key,
+	     16,
+	     data,
+	     len,
+	     hash,
+	     &hlen);
+
+	/* Copy to the output location */
+	memcpy(icv, hash, 12);
+
+	return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+
+static
+enum crypto_alg_err md5_check(odp_crypto_op_params_t *params,
+			      odp_crypto_generic_session_t *session)
+{
+	uint8_t *data  = odp_packet_buf_addr(params->out_pkt);
+	uint8_t *icv   = data;
+	uint32_t len   = params->auth_range.length;
+	uint8_t  hash_in[EVP_MAX_MD_SIZE];
+	uint8_t  hash_out[EVP_MAX_MD_SIZE];
+	uint32_t hlen = 12;
+
+	/* Adjust pointer for beginning of area to auth */
+	data += params->auth_range.offset;
+	icv  += params->hash_result_offset;
+
+	/* Copy current value out and clear it before authentication */
+	memset(hash_in, 0, sizeof(hash_in));
+	memcpy(hash_in, icv, hlen);
+	memset(icv, 0, hlen);
+	memset(hash_out, 0, sizeof(hash_out));
+
+	/* Hash it */
+	HMAC(EVP_md5(),
+	     session->auth.data.md5.key,
+	     16,
+	     data,
+	     len,
+	     hash_out,
+	     &hlen);
+
+	/* Verify match */
+	if (0 != memcmp(hash_in, hash_out, 12))
+		return ODP_CRYPTO_ALG_ERR_ICV_CHECK;
+
+	/* Matched */
+	return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+enum crypto_alg_err des_encrypt(odp_crypto_op_params_t *params,
+				odp_crypto_generic_session_t *session)
+{
+	uint8_t *data  = odp_packet_buf_addr(params->out_pkt);
+	uint32_t len   = params->cipher_range.length;
+	DES_cblock *iv;
+	DES_cblock iv_temp;
+
+	/*
+	 * Create a copy of the IV.  The DES library modifies IV
+	 * and if we are processing packets on parallel threads
+	 * we could get corruption.
+	 */
+	memcpy(iv_temp, session->cipher.iv.data, sizeof(iv_temp));
+	iv = &iv_temp;
+
+	/* Adjust pointer for beginning of area to cipher */
+	data += params->cipher_range.offset;
+
+	/* Override IV if requested */
+	if (params->override_iv_ptr)
+		iv = (DES_cblock *)params->override_iv_ptr;
+
+	/* Encrypt it */
+	DES_ede3_cbc_encrypt(data,
+			     data,
+			     len,
+			     &session->cipher.data.des.ks1,
+			     &session->cipher.data.des.ks2,
+			     &session->cipher.data.des.ks3,
+			     iv,
+			     1);
+
+	return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+enum crypto_alg_err des_decrypt(odp_crypto_op_params_t *params,
+				odp_crypto_generic_session_t *session)
+{
+	uint8_t *data  = odp_packet_buf_addr(params->out_pkt);
+	uint32_t len   = params->cipher_range.length;
+	DES_cblock *iv = (DES_cblock *)session->cipher.iv.data;
+
+	/* Adjust pointer for beginning of area to cipher */
+	data += params->cipher_range.offset;
+
+	/* Override IV if requested */
+	if (params->override_iv_ptr)
+		iv = (DES_cblock *)params->override_iv_ptr;
+
+	/* Decrypt it */
+	DES_ede3_cbc_encrypt(data,
+			     data,
+			     len,
+			     &session->cipher.data.des.ks1,
+			     &session->cipher.data.des.ks2,
+			     &session->cipher.data.des.ks3,
+			     iv,
+			     0);
+
+	return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+int process_des_params(odp_crypto_generic_session_t *session,
+		       odp_crypto_session_params_t *params)
+{
+	/* Verify IV len is either 0 or 8 */
+	if (!((0 == params->iv.length) || (8 == params->iv.length)))
+		return -1;
+
+	/* Verify IV pointer */
+	if (params->iv.length && !params->iv.data)
+		return -1;
+
+	/* Set function */
+	if (ODP_CRYPTO_OP_ENCODE == params->op)
+		session->cipher.func = des_encrypt;
+	else
+		session->cipher.func = des_decrypt;
+
+	/* Convert keys */
+	DES_set_key((DES_cblock *)&params->cipher_key.data[0],
+		    &session->cipher.data.des.ks1);
+	DES_set_key((DES_cblock *)&params->cipher_key.data[8],
+		    &session->cipher.data.des.ks2);
+	DES_set_key((DES_cblock *)&params->cipher_key.data[16],
+		    &session->cipher.data.des.ks3);
+
+	return 0;
+}
+
+static
+int process_md5_params(odp_crypto_generic_session_t *session,
+		       odp_crypto_session_params_t *params)
+{
+	/* Set function */
+	if (ODP_CRYPTO_OP_ENCODE == params->op)
+		session->auth.func = md5_gen;
+	else
+		session->auth.func = md5_check;
+
+	/* Convert keys */
+	memcpy(session->auth.data.md5.key, params->auth_key.data, 16);
+
+	return 0;
+}
+
+int
+odp_crypto_session_create(odp_crypto_session_params_t *params,
+			  odp_crypto_session_t *session_out,
+			  enum odp_crypto_ses_create_err *status)
+{
+	int rc;
+	odp_crypto_generic_session_t *session;
+
+	/* Default to successful result */
+	*status = ODP_CRYPTO_SES_CREATE_ERR_NONE;
+
+	/* Allocate memory for this session */
+	session = alloc_session();
+	if (NULL == session) {
+		*status = ODP_CRYPTO_SES_CREATE_ERR_ENOMEM;
+		return -1;
+	}
+
+	/* Derive order */
+	if (ODP_CRYPTO_OP_ENCODE == params->op)
+		session->do_cipher_first =  params->auth_cipher_text;
+	else
+		session->do_cipher_first = !params->auth_cipher_text;
+
+	/* Copy stuff over */
+	session->op = params->op;
+	session->compl_queue = params->compl_queue;
+	session->cipher.alg  = params->cipher_alg;
+	session->cipher.iv.data = params->iv.data;
+	session->cipher.iv.len  = params->iv.length;
+	session->auth.alg  = params->auth_alg;
+	session->output_pool = params->output_pool;
+
+	/* Process based on cipher */
+	switch (params->cipher_alg) {
+	case ODP_CIPHER_ALG_NULL:
+		session->cipher.func = null_crypto_routine;
+		rc = 0;
+		break;
+	case ODP_CIPHER_ALG_DES:
+	case ODP_CIPHER_ALG_3DES_CBC:
+		rc = process_des_params(session, params);
+		break;
+	default:
+		rc = -1;
+	}
+
+	/* Check result */
+	if (rc) {
+		*status = ODP_CRYPTO_SES_CREATE_ERR_INV_CIPHER;
+		return -1;
+	}
+
+	/* Process based on auth */
+	switch (params->auth_alg) {
+	case ODP_AUTH_ALG_NULL:
+		session->auth.func = null_crypto_routine;
+		rc = 0;
+		break;
+	case ODP_AUTH_ALG_MD5_96:
+		rc = process_md5_params(session, params);
+		break;
+	default:
+		rc = -1;
+	}
+
+	/* Check result */
+	if (rc) {
+		*status = ODP_CRYPTO_SES_CREATE_ERR_INV_AUTH;
+		return -1;
+	}
+
+	/* We're happy */
+	*session_out = (intptr_t)session;
+	return 0;
+}
+
+int
+odp_crypto_session_create_async(odp_crypto_session_params_t *params,
+				odp_buffer_t completion_event,
+				odp_queue_t completion_queue)
+{
+	odp_crypto_generic_session_result_t *result;
+
+	result = odp_buffer_addr(completion_event);
+	if (odp_crypto_session_create(params, &result->session, &result->rc))
+		return -1;
+	odp_queue_enq(completion_queue, completion_event);
+	return 0;
+}
+
+
+int
+odp_crypto_operation(odp_crypto_op_params_t *params,
+		     bool *posted,
+		     odp_buffer_t completion_event)
+{
+	enum crypto_alg_err rc_cipher = ODP_CRYPTO_ALG_ERR_NONE;
+	enum crypto_alg_err rc_auth = ODP_CRYPTO_ALG_ERR_NONE;
+	odp_crypto_generic_session_t *session;
+	odp_crypto_generic_op_result_t *result;
+
+	*posted = 0;
+	session = (odp_crypto_generic_session_t *)(intptr_t)params->session;
+
+	/* Resolve output buffer */
+	if (ODP_PACKET_INVALID == params->out_pkt)
+		if (ODP_BUFFER_POOL_INVALID != session->output_pool)
+			params->out_pkt =
+				odp_buffer_alloc(session->output_pool);
+	if (params->pkt != params->out_pkt) {
+		if (odp_unlikely(ODP_PACKET_INVALID == params->out_pkt))
+			abort();
+		odp_packet_copy(params->out_pkt, params->pkt);
+		if (completion_event == odp_buffer_from_packet(params->pkt))
+			completion_event =
+				odp_buffer_from_packet(params->out_pkt);
+		odp_packet_free(params->pkt);
+		params->pkt = ODP_PACKET_INVALID;
+	}
+
+	/* Invoke the functions */
+	if (session->do_cipher_first) {
+		rc_cipher = session->cipher.func(params, session);
+		rc_auth = session->auth.func(params, session);
+	} else {
+		rc_auth = session->auth.func(params, session);
+		rc_cipher = session->cipher.func(params, session);
+	}
+
+	/* Build Result (no HW so no errors) */
+	result = get_op_result_from_buffer(completion_event);
+	result->magic = OP_RESULT_MAGIC;
+	result->cipher.alg_err = rc_cipher;
+	result->cipher.hw_err = ODP_CRYPTO_HW_ERR_NONE;
+	result->auth.alg_err = rc_auth;
+	result->auth.hw_err = ODP_CRYPTO_HW_ERR_NONE;
+
+	/*
+	 * robking: a) the queue is supposed to come from session
+	 *          b) ordering question asks whether we must
+	 *             use the packet to return status
+	 */
+	if (ODP_QUEUE_INVALID != session->compl_queue) {
+		odp_queue_enq(session->compl_queue, completion_event);
+		*posted = 1;
+	}
+	return 0;
+}
+
+
+int
+odp_crypto_init(uint32_t max_sessions)
+{
+	size_t mem_size;
+
+	/* Force down to our limit */
+	if (MAX_SESSIONS < max_sessions)
+		max_sessions = MAX_SESSIONS;
+
+	/* Calculate the memory size we need */
+	mem_size  = sizeof(*global);
+	mem_size += (max_sessions * sizeof(odp_crypto_generic_session_t));
+
+	/* Allocate our globally shared memory */
+	global = odp_shm_reserve("crypto_pool", mem_size, ODP_CACHE_LINE_SIZE);
+
+	/* Clear it out */
+	memset(global, 0, mem_size);
+
+	/* Initialize it */
+	global->max = max_sessions;
+
+	return 0;
+}
+
+int
+odp_hw_random_get(uint8_t *buf, size_t *len, bool use_entropy ODP_UNUSED)
+{
+	int rc;
+	rc = RAND_bytes(buf, *len);
+	return ((1 == rc) ? 0 : -1);
+}
+
+void
+odp_crypto_get_operation_compl_status(odp_buffer_t completion_event,
+				      odp_crypto_compl_status_t *auth,
+				      odp_crypto_compl_status_t *cipher)
+{
+	odp_crypto_generic_op_result_t *result;
+
+	result = get_op_result_from_buffer(completion_event);
+
+	if (OP_RESULT_MAGIC != result->magic)
+		abort();
+
+	memcpy(auth, &result->auth, sizeof(*auth));
+	memcpy(cipher, &result->cipher, sizeof(*cipher));
+}
+
+void
+odp_crypto_get_ses_create_compl_status(odp_buffer_t completion_event,
+				       enum odp_crypto_ses_create_err *status)
+{
+	odp_crypto_generic_session_result_t *result;
+
+	result = odp_buffer_addr(completion_event);
+	*status = result->rc;
+}
+
+void
+odp_crypto_get_ses_create_compl_session(odp_buffer_t completion_event,
+					odp_crypto_session_t *session)
+{
+	odp_crypto_generic_session_result_t *result;
+
+	result = odp_buffer_addr(completion_event);
+	*session = result->session;
+}