From patchwork Tue May 27 14:44:42 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robbie King X-Patchwork-Id: 30980 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-vc0-f198.google.com (mail-vc0-f198.google.com [209.85.220.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 790842066E for ; Tue, 27 May 2014 14:45:28 +0000 (UTC) Received: by mail-vc0-f198.google.com with SMTP id ij19sf34726740vcb.9 for ; Tue, 27 May 2014 07:45:28 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:thread-topic:thread-index :date:message-id:references:in-reply-to:accept-language:mime-version :subject:precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list:content-language :content-type:content-transfer-encoding; bh=fUGJ/bpdJKC88l+TudquyLAL/bJnXi+HksHkjff2YNQ=; b=dhJY0G1YEnccYBIEYVxXaSl84OvoZbYaMSXqKPEHZXWe/L5YDpSP4GJYnCk1ihGJBw mHKqcscm8rBt2RaRJwqYKyt9Vesg6syA3Ih4m7kPQrdhoIgXjDMkacgMeTQTpClqYqaO c0Ao4eZBr0/XuIwOhiR1JyyywqSUVtEKFcHiWB4+q4yA4vIqsbAqz6mE93/pJakzg1+B 39JtvypfOXPUJnhb6cPYYMow08H5hzRIPWVnFo8mx6FCbjeBrclOjaG+uXBPBOS4nF2U 4RinvciQ1nreD2ERNuq1v2XgmtoIC10t2SHZTWY67nmLPBzVo1htEz8GJpZ02RyvLqf2 Wy8w== X-Gm-Message-State: ALoCoQne9a5Br9yKxXHRjFFTE7hyULPJ8sx4sk9Gg41IulIssfPMA29xa6ozHpQbLF51XNh1H8ia X-Received: by 10.236.89.114 with SMTP id b78mr12021513yhf.13.1401201928293; Tue, 27 May 2014 07:45:28 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.29.4 with SMTP id a4ls3149714qga.45.gmail; Tue, 27 May 2014 07:45:28 -0700 (PDT) X-Received: by 10.58.29.106 with SMTP id j10mr18233305veh.31.1401201928138; Tue, 27 May 2014 07:45:28 -0700 (PDT) Received: from mail-ve0-x235.google.com (mail-ve0-x235.google.com [2607:f8b0:400c:c01::235]) by mx.google.com with ESMTPS id s1si8268556vep.80.2014.05.27.07.45.28 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 27 May 2014 07:45:28 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c01::235 as permitted sender) client-ip=2607:f8b0:400c:c01::235; Received: by mail-ve0-f181.google.com with SMTP id pa12so10842344veb.12 for ; Tue, 27 May 2014 07:45:28 -0700 (PDT) X-Received: by 10.220.44.141 with SMTP id a13mr1125620vcf.71.1401201927966; Tue, 27 May 2014 07:45:27 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.221.72 with SMTP id ib8csp124896vcb; Tue, 27 May 2014 07:45:27 -0700 (PDT) X-Received: by 10.140.101.78 with SMTP id t72mr41129630qge.79.1401201927272; Tue, 27 May 2014 07:45:27 -0700 (PDT) Received: from ip-10-141-164-156.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id s5si17066790qce.31.2014.05.27.07.44.57 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 27 May 2014 07:45:27 -0700 (PDT) Received-SPF: none (google.com: lng-odp-bounces@lists.linaro.org does not designate permitted sender hosts) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-141-164-156.ec2.internal) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1WpIbR-00042B-BO; Tue, 27 May 2014 14:43:45 +0000 Received: from alln-iport-6.cisco.com ([173.37.142.93]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1WpIbK-000426-A7 for lng-odp@lists.linaro.org; Tue, 27 May 2014 14:43:38 +0000 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgsFAP+jhFOtJV2c/2dsb2JhbABZgmUigSq6YIc6AYEOFnSCJQEBAQQBAhcNEw0+BAIBCBEEAQELFBAoCh0IAgQTCIg6AbVwn08XjXoBJjgGgyWBFQSVcoEglgiDOIFtAR8i X-IronPort-AV: E=Sophos;i="4.98,919,1392163200"; d="scan'208";a="47570305" Received: from rcdn-core-5.cisco.com ([173.37.93.156]) by alln-iport-6.cisco.com with ESMTP; 27 May 2014 14:44:43 +0000 Received: from xhc-rcd-x07.cisco.com (xhc-rcd-x07.cisco.com [173.37.183.81]) by rcdn-core-5.cisco.com (8.14.5/8.14.5) with ESMTP id s4REih8x014642 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL) for ; Tue, 27 May 2014 14:44:43 GMT Received: from xmb-aln-x01.cisco.com ([fe80::747b:83e1:9755:d453]) by xhc-rcd-x07.cisco.com ([173.37.183.81]) with mapi id 14.03.0123.003; Tue, 27 May 2014 09:44:43 -0500 From: "Robbie King (robking)" To: "lng-odp@lists.linaro.org" Thread-Topic: [PATCH] linux-generic crypto Thread-Index: AQHPd1qqLUb24+uNwU63D4MDHuSZBptUfkaQ Date: Tue, 27 May 2014 14:44:42 +0000 Message-ID: References: <1400940946-21262-1-git-send-email-robking@cisco.com> In-Reply-To: <1400940946-21262-1-git-send-email-robking@cisco.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [64.102.83.121] MIME-Version: 1.0 X-Topics: crypto patch Subject: Re: [lng-odp] [PATCH] linux-generic crypto X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: lng-odp-bounces@lists.linaro.org X-Original-Sender: robking@cisco.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c01::235 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=neutral (body hash did not verify) header.i=@ Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 Content-Language: en-US My apologies for not including the "TODO" list with the patch. - Add support for scatter/gather. - Add support for "new buffer" (versus in place) - Add missing accessor functions defined in the specification Also a few things I would appreciate feedback on. - Update to a more consistent API naming convention. What is in this patch is mostly directly from the design document. At a minimum everything crypto specific should be begin with "odp_crypto_", and anything we think will become generic as we add more HW assists would move into other files and become "odp_". - Typedef everything, including enums? FWIW, I like the convention of the "_t" suffix for typedef'd structs and unions, and "_e" for enums. But I realize we are trying to be "kernel like". I do think at a minimum all structs/unions should be typedef'd. - Would like to refine return code definitions to look more consistent. -----Original Message----- From: Robbie King (robking) Sent: Saturday, May 24, 2014 10:16 AM To: lng-odp@lists.linaro.org Cc: Robbie King (robking) Subject: [PATCH] linux-generic crypto Initial linux-generic crypto implementation. Note that these changes require installing and linking with libssl-dev. The camel case warnings are also due to calls into libssl-dev. Signed-off-by: Robbie King --- include/odp_crypto.h | 295 +++++++++++++ platform/linux-generic/Makefile | 1 + .../linux-generic/include/odp_crypto_internal.h | 86 ++++ platform/linux-generic/source/odp_crypto.c | 434 ++++++++++++++++++++ 4 files changed, 816 insertions(+), 0 deletions(-) create mode 100644 include/odp_crypto.h create mode 100644 platform/linux-generic/include/odp_crypto_internal.h create mode 100644 platform/linux-generic/source/odp_crypto.c diff --git a/include/odp_crypto.h b/include/odp_crypto.h new file mode 100644 index 0000000..c733875 --- /dev/null +++ b/include/odp_crypto.h @@ -0,0 +1,295 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/** + * @file + * + * ODP crypto + */ + +#ifndef ODP_CRYPTO_H_ +#define ODP_CRYPTO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + +/** Invalid session handle */ +#define ODP_CRYPTO_SESSION_INVALID (-1ULL) + +/** + * Crypto API opaque session handle + */ +typedef uint64_t odp_crypto_session_t; + +/** + * Crypto API operation mode + */ +enum odp_crypto_op_mode { + ODP_CRYPTO_SYNC, /**< Synchronous, return results immediately */ + ODP_CRYPTO_ASYNC, /**< Aynchronous, return results via posted event */ +}; + +/** + * Crypto API operation type + */ +enum odp_crypto_op { + ODP_CRYPTO_OP_ENCODE, /**< Encrypt and/or compute authentication ICV */ + ODP_CRYPTO_OP_DECODE /**< Decrypt and/or verify authentication ICV */ +}; + +/** + * Crypto API cipher algorithm + */ +enum odp_cipher_alg { + ODP_CIPHER_ALG_NULL, /**< No cipher algorithm specified */ + ODP_CIPHER_ALG_DES, /**< DES */ + ODP_CIPHER_ALG_3DES_CBC, /**< Triple DES with cipher block chaining */ +}; + +/** + * Crypto API authentication algorithm + */ +enum odp_auth_alg { + ODP_AUTH_ALG_NULL, /**< No authentication algorithm specified */ + ODP_AUTH_ALG_MD5_96, /**< HMAC-MD5 with 96 bit key */ }; + +/** + * Crypto API operation order + */ +enum odp_crypto_combination { + ODP_CRYPTO_CIPHER_ONLY, /**< Only perform cipher */ + ODP_CRYPTO_AUTH_ONLY, /**< Only perform authentication */ + ODP_CRYPTO_AUTH_CIPHERTEXT /**< Cipher then authentication on encode +*/ }; + +/** + * Crypto API key + */ +typedef struct odp_key_s { + union { + /** DES/3DES key definition (set all same for DES) */ + struct { + uint8_t k1[8]; /**< First key */ + uint8_t k2[8]; /**< Second key */ + uint8_t k3[8]; /**< Third key */ + } des; + /** MD5 key */ + struct { + uint8_t key[16]; /**< Key up to 128 bits */ + } md5; + }; +} odp_key_t; + +/** + * Crypto API data range specifier + */ +struct odp_data_range { + uint16_t offset; /**< Offset from beginning of buffer (chain) */ + uint16_t length; /**< Length of data to operate on */ }; + +/** + * Crypto API session creation paramters + * + * TODO: add "odp_session_proc_info_t" + */ +struct odp_crypto_session_params { + enum odp_crypto_op op; /**< Encode versus decode */ + enum odp_crypto_combination comb; /**< Operation order */ + enum odp_crypto_op_mode pref_mode; /**< Preferred sync vs async */ + enum odp_cipher_alg cipher_alg; /**< Cipher algorithm */ + odp_key_t *cipher_key; /**< Cipher key */ + uint8_t *iv; /**< Cipher Initialization Vector (IV) */ + size_t iv_len; /**< Cipher IV length */ + enum odp_auth_alg auth_alg; /**< Authentication algorithm */ + odp_key_t *auth_key; /**< Authentication key */ + odp_queue_t compl_queue; /**< Async mode completion event queue */ +}; + +/** + * Crypto API per packet operation parameters */ struct +odp_crypto_op_params { + odp_crypto_session_t session; /**< Session handle from creation */ + odp_packet_t pkt; /**< Input packet buffer */ + odp_packet_t out_pkt; /**< Output packet buffer (optional) */ + uint8_t *override_iv_ptr; /**< Override session IV pointer */ + unsigned hash_result_offset; /**< Offset from start of packet buffer for hash result */ + struct odp_data_range cipher_range; /**< Data range to apply cipher */ + struct odp_data_range auth_range; /**< Data range to authenticate */ +}; + +/** + * Crypto API session creation return code + * + * TODO: seems confusing, maybe _rc instead */ enum +odp_crypto_ses_create_err { + ODP_CRYPTO_SES_CREATE_NONE, /**< No session created? need to clarify */ + ODP_CRYPTO_SES_CREATE_OK, /**< Session created successfully */ +}; + +/** + * Crypto API algorithm return code + */ +enum crypto_alg_err { + ODP_CRYPTO_ALG_ERR_NONE, /**< Algorithm successful */ + ODP_CRYPTO_ALG_ERR_DATA_SIZE, /**< Invalid data block size */ + ODP_CRYPTO_ALG_ERR_KEY_SIZE, /**< Key size invalid for algorithm */ + ODP_CRYPTO_ALG_ERR_ICV_CHECK, /**< Computed ICV value mismatch */ }; + +/** + * Crypto API operation return code + */ +typedef enum odp_crypto_rc { + ODP_CRYPTO_OP_OK, /**< Operation completed, results are valid */ + ODP_CRYPTO_OP_POSTED, /**< Operation was posted, results delivered via completion queue */ + ODP_CRYPTO_OP_ERROR, /**< Operation failed */ +} odp_crypto_rc_e; + +/** + * Crypto API hardware centric return code */ enum crypto_hw_err { + ODP_CRYPTO_HW_ERR_NONE, /**< Operation completed successfully */ + ODP_CRYPTO_HW_ERR_DMA, /**< Error detected during DMA of data */ + ODP_CRYPTO_HW_ERR_BP_DEPLETED, /**< Operation failed due to buffer +pool depletion */ }; + +/** + * Crypto API algorithm (cipher or authentication) */ typedef union +odp_crypto_alg_u { + enum odp_cipher_alg cipher; /**< Cipher algorithm */ + enum odp_auth_alg auth; /**< Authentication algorithm */ +} odp_crypto_alg_t; + +/** + * Cryto API per packet operation completion status */ struct +odp_crypto_compl_status { + odp_crypto_alg_t alg; /**< Requested algorithm */ + enum crypto_alg_err alg_err; /**< Algorithm specific return code */ + enum crypto_hw_err hw_err; /**< Hardware specific return code */ +}; + + +/** + * Crypto session creation + * + * Create a crypto session. Operation occurs asynchronously if a +completion + * queue is specified else synchronously. + * + * @param params Session parameters + * @param completion_event Event by which the session creation results are + * delivered. + * @param completion_queue Queue by which the completion event will be + * delivered. Ignored if ODP_QUEUE_INVALID. + * + * @return Operation return code indicating success or failure for + * when synchronous operation requested, else POSTED when + * asynchronous operation is requested. + */ +odp_crypto_rc_e +odp_crypto_session_create(struct odp_crypto_session_params *params, + odp_buffer_t completion_event, + odp_queue_t completion_queue); + + +/** + * Crypto session creation completion status + * + * Accessor function for obtaining creation status from the completion event. + * + * @param completion_event Event containing operation results + * @param status Pointer to store creation return code + */ +void +odp_crypto_get_ses_create_compl_status(odp_buffer_t completion_event, + enum odp_crypto_ses_create_err *status); + +/** + * Crypto session creation completion return value + * + * Accessor function for obtaining handle for newly created session. + * + * @param completion_event Event containing operation results + * @param session Pointer to store session handle + */ +void +odp_crypto_get_ses_create_compl_session(odp_buffer_t completion_event, + odp_crypto_session_t *session); + +/** + * Crypto per packet operation + * + * Performs the cryptographic operations specified during session +creation + * on the packet. + * + * @param params Operation parameters + * @param completion_event Event by which the session creation results are + * delivered. + * + * @return Operation return code indicating success or failure when session + * indicates synchronous operation, else POSTED for asynchronous + * operation. + */ +odp_crypto_rc_e +odp_crypto_operation(struct odp_crypto_op_params *params, + odp_buffer_t completion_event); + + +/** + * Crypto per packet operation completion status + * + * Accessor function for obtaining operation status from the completion event. + * + * @param completion_event Event containing operation results + * @param auth Pointer to store authentication results + * @param cipher Pointer to store cipher results + */ +void +odp_crypto_get_operation_compl_status(odp_buffer_t completion_event, + struct odp_crypto_compl_status *auth, + struct odp_crypto_compl_status *cipher); + +/** + * Generate random byte string + * + * @param buf Pointer to store result + * @param len Pointer to input length value as well as return value + * @param use_entropy (TODO: needs description) + * + * @return 0 if succesful + */ +int +odp_hw_random_get(uint8_t *buf, uint32_t *len, bool use_entropy); + +/** + * Initialize the crypto subsystem, called once from main thread + * + * @param max_sessions Maximum number of sessions to support + * + * @return 0 if succesful + */ +int +odp_crypto_init(uint32_t max_sessions); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/Makefile b/platform/linux-generic/Makefile index ec5d4a7..57f6d18 100644 --- a/platform/linux-generic/Makefile +++ b/platform/linux-generic/Makefile @@ -72,6 +72,7 @@ OBJS += $(OBJ_DIR)/odp_time.o OBJS += $(OBJ_DIR)/odp_timer.o OBJS += $(OBJ_DIR)/odp_ring.o OBJS += $(OBJ_DIR)/odp_rwlock.o +OBJS += $(OBJ_DIR)/odp_crypto.o ifeq ($(ODP_HAVE_NETMAP),yes) OBJS += $(OBJ_DIR)/odp_packet_netmap.o endif 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..e558864 --- /dev/null +++ b/platform/linux-generic/include/odp_crypto_internal.h @@ -0,0 +1,86 @@ +/* Copyright (c) 2013, 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 + +#define OP_RESULT_MAGIC 0x91919191 + +/** Forward declaration of session structure */ struct +odp_crypto_session_s; + +/** + * Algorithm handler function prototype */ typedef enum crypto_alg_err +(*crypto_func_t)(struct odp_crypto_op_params *params, + struct odp_crypto_session_s *session); + +/** + * Per crypto session data structure + */ +struct odp_crypto_session_s { + uint32_t index; + enum odp_crypto_op op; + enum odp_crypto_combination comb; + odp_queue_t compl_queue; + 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 + */ +struct odp_operation_result_s { + uint32_t magic; + struct odp_crypto_compl_status cipher; + struct odp_crypto_compl_status auth; +}; + +/** + * Per session creation operation result */ struct +odp_session_result_s { + enum odp_crypto_ses_create_err rc; + odp_crypto_session_t session; +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/platform/linux-generic/source/odp_crypto.c b/platform/linux-generic/source/odp_crypto.c new file mode 100644 index 0000000..6162510 --- /dev/null +++ b/platform/linux-generic/source/odp_crypto.c @@ -0,0 +1,434 @@ +/* Copyright (c) 2013, Linaro Limited + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define MAX_SESSIONS 32 + +typedef struct { + odp_atomic_u32_t next; + uint32_t max; + struct odp_crypto_session_s 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 +struct odp_operation_result_s *get_op_result_from_buffer(odp_buffer_t +buf) { + uint8_t *temp; + struct odp_operation_result_s *result; + + temp = odp_buffer_addr(buf); + temp += odp_buffer_size(buf); + result = (struct odp_operation_result_s *)(temp - sizeof(*result)); + return result; +} + +static +struct odp_crypto_session_s *alloc_session(void) { + uint32_t idx; + struct odp_crypto_session_s *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( + struct odp_crypto_op_params *params ODP_UNUSED, + struct odp_crypto_session_s *session ODP_UNUSED) { + return ODP_CRYPTO_ALG_ERR_NONE; +} + +static +enum crypto_alg_err md5_gen(struct odp_crypto_op_params *params, + struct odp_crypto_session_s *session) { + uint8_t *data = odp_packet_buf_addr(params->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(struct odp_crypto_op_params *params, + struct odp_crypto_session_s *session) { + uint8_t *data = odp_packet_buf_addr(params->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; + + /* Copy current value out and clear it before authentication */ + memcpy(hash, icv, hlen); + memset(icv, 0, hlen); + + /* Hash it */ + HMAC(EVP_md5(), session->auth.data.md5.key, 16, data, len, icv, +&hlen); + + /* Verify match */ + if (0 != memcmp(icv, hash, 12)) + return ODP_CRYPTO_ALG_ERR_ICV_CHECK; + + /* Matched */ + return ODP_CRYPTO_ALG_ERR_NONE; +} + +static +enum crypto_alg_err des_encrypt(struct odp_crypto_op_params *params, + struct odp_crypto_session_s *session) { + uint8_t *data = odp_packet_buf_addr(params->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; + + /* 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(struct odp_crypto_op_params *params, + struct odp_crypto_session_s *session) { + uint8_t *data = odp_packet_buf_addr(params->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(struct odp_crypto_session_s *session, + struct odp_crypto_session_params *params) { + /* Verify IV len is either 0 or 8 */ + if (!((0 == params->iv_len) || (8 == params->iv_len))) + return -1; + + /* Verify IV pointer */ + if (params->iv_len && !params->iv) + 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(¶ms->cipher_key->des.k1, &session->cipher.data.des.ks1); + DES_set_key(¶ms->cipher_key->des.k2, &session->cipher.data.des.ks2); + DES_set_key(¶ms->cipher_key->des.k3, +&session->cipher.data.des.ks3); + + return 0; +} + +static +int process_md5_params(struct odp_crypto_session_s *session, + struct odp_crypto_session_params *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->md5.key, 16); + + return 0; +} + +odp_crypto_rc_e +odp_crypto_session_create(struct odp_crypto_session_params *params, + odp_buffer_t completion_event, + odp_queue_t completion_queue) +{ + int rc; + struct odp_crypto_session_s *session; + struct odp_session_result_s *result = +odp_buffer_addr(completion_event); + + /* Default to failure result */ + result->rc = ODP_CRYPTO_SES_CREATE_NONE; + result->session = ODP_CRYPTO_SESSION_INVALID; + + /* Allocate memory for this session */ + session = alloc_session(); + if (NULL == session) + return ODP_CRYPTO_OP_ERROR; + + /* Copy stuff over */ + session->op = params->op; + session->comb = params->comb; + session->compl_queue = params->compl_queue; + session->cipher.alg = params->cipher_alg; + session->cipher.iv.data = params->iv; + session->cipher.iv.len = params->iv_len; + session->auth.alg = params->auth_alg; + + /* 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) + return ODP_CRYPTO_OP_ERROR; + + /* 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) + return ODP_CRYPTO_OP_ERROR; + + /* We're happy */ + result->rc = ODP_CRYPTO_SES_CREATE_OK; + result->session = (intptr_t)session; + + /* If there is a queue post else we're good */ + if (ODP_QUEUE_INVALID != completion_queue) { + odp_queue_enq(completion_queue, completion_event); + return ODP_CRYPTO_OP_POSTED; + } + + return ODP_CRYPTO_OP_OK; +} + + +odp_crypto_rc_e +odp_crypto_operation(struct odp_crypto_op_params *params, + 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; + struct odp_crypto_session_s *session; + struct odp_operation_result_s *result; + + session = (struct odp_crypto_session_s *)(intptr_t)params->session; + + /* + * robking: need to understand infrastructure for scattered packets + * for now just don't support them + */ + if (odp_buffer_is_scatter(odp_buffer_from_packet(params->pkt))) + return ODP_CRYPTO_OP_ERROR; + + /* + * robking: for now we are only going to support in place + */ + if (params->pkt != params->out_pkt) + return ODP_CRYPTO_OP_ERROR; + + /* Invoke the functions */ + switch (session->comb) { + case ODP_CRYPTO_CIPHER_ONLY: + rc_cipher = session->cipher.func(params, session); + break; + case ODP_CRYPTO_AUTH_ONLY: + rc_auth = session->auth.func(params, session); + break; + case ODP_CRYPTO_AUTH_CIPHERTEXT: + if (ODP_CRYPTO_OP_ENCODE == session->op) { + 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); + } + break; + } + + /* Build Result (no HW so no errors) */ + result = get_op_result_from_buffer(completion_event); + result->magic = OP_RESULT_MAGIC; + result->cipher.alg.cipher = session->cipher.alg; + result->cipher.alg_err = rc_cipher; + result->cipher.hw_err = ODP_CRYPTO_HW_ERR_NONE; + result->auth.alg.auth = session->auth.alg; + 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); + return ODP_CRYPTO_OP_POSTED; + } + + return ODP_CRYPTO_OP_OK; +} + + +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(struct odp_crypto_session_s)); + + /* 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, uint32_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, + struct odp_crypto_compl_status *auth, + struct odp_crypto_compl_status *cipher) { + struct odp_operation_result_s *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) { + struct odp_session_result_s *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) +{ + struct odp_session_result_s *result; + + result = odp_buffer_addr(completion_event); + *session = result->session; +} -- 1.7.7.6 _______________________________________________ lng-odp mailing list lng-odp@lists.linaro.org http://lists.linaro.org/mailman/listinfo/lng-odp