summaryrefslogtreecommitdiff
path: root/drivers/mxc/security/sahara2/fsl_shw_sym.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mxc/security/sahara2/fsl_shw_sym.c')
-rw-r--r--drivers/mxc/security/sahara2/fsl_shw_sym.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/drivers/mxc/security/sahara2/fsl_shw_sym.c b/drivers/mxc/security/sahara2/fsl_shw_sym.c
new file mode 100644
index 000000000000..133b92dad3c1
--- /dev/null
+++ b/drivers/mxc/security/sahara2/fsl_shw_sym.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file fsl_shw_sym.c
+ *
+ * This file implements Symmetric Cipher functions of the FSL SHW API for
+ * Sahara. This does not include CCM.
+ */
+
+#include "sahara.h"
+#include "fsl_platform.h"
+
+#include "sf_util.h"
+#include "adaptor.h"
+
+#ifdef LINUX_KERNEL
+EXPORT_SYMBOL(fsl_shw_symmetric_encrypt);
+EXPORT_SYMBOL(fsl_shw_symmetric_decrypt);
+#endif
+
+#if defined(NEED_CTR_WORKAROUND)
+/* CTR mode needs block-multiple data in/out */
+#define LENGTH_PATCH (sym_ctx->block_size_bytes)
+#define LENGTH_PATCH_MASK (sym_ctx->block_size_bytes-1)
+#else
+#define LENGTH_PATCH 0
+#define LENGTH_PATCH_MASK 0 /* du not use! */
+#endif
+
+/*!
+ * Block of zeroes which is maximum Symmetric block size, used for
+ * initializing context register, etc.
+ */
+static uint32_t block_zeros[4] = {
+ 0, 0, 0, 0
+};
+
+typedef enum cipher_direction {
+ SYM_DECRYPT,
+ SYM_ENCRYPT
+} cipher_direction_t;
+
+/*!
+ * Create and run the chain for a symmetric-key operation.
+ *
+ * @param user_ctx Who the user is
+ * @param key_info What key is to be used
+ * @param sym_ctx Info details about algorithm
+ * @param encrypt 0 = decrypt, non-zero = encrypt
+ * @param length Number of octets at @a in and @a out
+ * @param in Pointer to input data
+ * @param out Location to store output data
+ *
+ * @return The status of handing chain to driver,
+ * or an earlier argument/flag or allocation
+ * error.
+ */
+static fsl_shw_return_t do_symmetric(fsl_shw_uco_t * user_ctx,
+ fsl_shw_sko_t * key_info,
+ fsl_shw_scco_t * sym_ctx,
+ cipher_direction_t encrypt,
+ uint32_t length,
+ const uint8_t * in, uint8_t * out)
+{
+ SAH_SF_DCLS;
+ uint8_t *sink = NULL;
+ sah_Link *link1 = NULL;
+ sah_Link *link2 = NULL;
+ sah_Oct_Str ptr1;
+ uint32_t size1 = sym_ctx->block_size_bytes;
+
+ SAH_SF_USER_CHECK();
+
+ /* Two different sets of chains, depending on algorithm */
+ if (key_info->algorithm == FSL_KEY_ALG_ARC4) {
+ if (sym_ctx->flags & FSL_SYM_CTX_INIT) {
+ /* Desc. #35 w/ARC4 - start from key */
+ header = SAH_HDR_ARC4_SET_MODE_KEY
+ ^ sah_insert_skha_algorithm_arc4;
+
+ DESC_IN_KEY(header, 0, NULL, key_info);
+ } else { /* load SBox */
+ /* Desc. #33 w/ARC4 and NO PERMUTE */
+ header = SAH_HDR_ARC4_SET_MODE_SBOX
+ ^ sah_insert_skha_no_permute
+ ^ sah_insert_skha_algorithm_arc4;
+ DESC_IN_IN(header, 256, sym_ctx->context,
+ 3, sym_ctx->context + 256);
+ } /* load SBox */
+
+ /* Add in-out data descriptor to process the data */
+ if (length != 0) {
+ DESC_IN_OUT(SAH_HDR_SKHA_ENC_DEC, length, in, length,
+ out);
+ }
+
+ /* Operation is done ... save what came out? */
+ if (sym_ctx->flags & FSL_SYM_CTX_SAVE) {
+ /* Desc. #34 - Read SBox, pointers */
+ header = SAH_HDR_ARC4_READ_SBOX;
+ DESC_OUT_OUT(header, 256, sym_ctx->context,
+ 3, sym_ctx->context + 256);
+ }
+ } else { /* not ARC4 */
+ /* Doing 1- or 2- descriptor chain. */
+ /* Desc. #1 and algorithm and mode */
+ header = SAH_HDR_SKHA_SET_MODE_IV_KEY
+ ^ sah_insert_skha_mode[sym_ctx->mode]
+ ^ sah_insert_skha_algorithm[key_info->algorithm];
+
+ /* Honor 'no key parity checking' for DES and TDES */
+ if ((key_info->flags & FSL_SKO_KEY_IGNORE_PARITY) &&
+ ((key_info->algorithm == FSL_KEY_ALG_DES) ||
+ (key_info->algorithm == FSL_KEY_ALG_TDES))) {
+ header ^= sah_insert_skha_no_key_parity;
+ }
+
+ /* Header by default is decrypting, so... */
+ if (encrypt == SYM_ENCRYPT) {
+ header ^= sah_insert_skha_encrypt;
+ }
+
+ if (sym_ctx->mode == FSL_SYM_MODE_CTR) {
+ header ^= sah_insert_skha_modulus[sym_ctx->modulus_exp];
+ }
+
+ if (sym_ctx->mode == FSL_SYM_MODE_ECB) {
+ ptr1 = NULL;
+ size1 = 0;
+ } else if (sym_ctx->flags & FSL_SYM_CTX_INIT) {
+ ptr1 = (uint8_t *) block_zeros;
+ } else {
+ ptr1 = sym_ctx->context;
+ }
+
+ DESC_IN_KEY(header, sym_ctx->block_size_bytes, ptr1, key_info);
+
+ /* Add in-out data descriptor */
+ if (length != 0) {
+ header = SAH_HDR_SKHA_ENC_DEC;
+ if (LENGTH_PATCH && (sym_ctx->mode == FSL_SYM_MODE_CTR)
+ && ((length & LENGTH_PATCH_MASK) != 0)) {
+ sink = DESC_TEMP_ALLOC(LENGTH_PATCH);
+ ret =
+ sah_Create_Link(user_ctx->mem_util, &link1,
+ (uint8_t *) in, length,
+ SAH_USES_LINK_DATA);
+ ret =
+ sah_Append_Link(user_ctx->mem_util, link1,
+ (uint8_t *) sink,
+ LENGTH_PATCH -
+ (length &
+ LENGTH_PATCH_MASK),
+ SAH_USES_LINK_DATA);
+ if (ret != FSL_RETURN_OK_S) {
+ goto out;
+ }
+ ret =
+ sah_Create_Link(user_ctx->mem_util, &link2,
+ out, length,
+ SAH_USES_LINK_DATA |
+ SAH_OUTPUT_LINK);
+ if (ret != FSL_RETURN_OK_S) {
+ goto out;
+ }
+ ret = sah_Append_Link(user_ctx->mem_util, link2,
+ sink,
+ LENGTH_PATCH -
+ (length &
+ LENGTH_PATCH_MASK),
+ SAH_USES_LINK_DATA);
+ if (ret != FSL_RETURN_OK_S) {
+ goto out;
+ }
+ ret =
+ sah_Append_Desc(user_ctx->mem_util,
+ &desc_chain, header, link1,
+ link2);
+ if (ret != FSL_RETURN_OK_S) {
+ goto out;
+ }
+ link1 = link2 = NULL;
+ } else {
+ DESC_IN_OUT(header, length, in, length, out);
+ }
+ }
+
+ /* Unload any desired context */
+ if (sym_ctx->flags & FSL_SYM_CTX_SAVE) {
+ DESC_OUT_OUT(SAH_HDR_SKHA_READ_CONTEXT_IV, 0, NULL,
+ sym_ctx->block_size_bytes,
+ sym_ctx->context);
+ }
+
+ } /* not ARC4 */
+
+ SAH_SF_EXECUTE();
+
+ out:
+ SAH_SF_DESC_CLEAN();
+ DESC_TEMP_FREE(sink);
+ if (LENGTH_PATCH) {
+ sah_Destroy_Link(user_ctx->mem_util, link1);
+ sah_Destroy_Link(user_ctx->mem_util, link2);
+ }
+
+ return ret;
+}
+
+/* REQ-S2LRD-PINTFC-API-BASIC-SYM-002 */
+/* PINTFC-API-BASIC-SYM-ARC4-001 */
+/* PINTFC-API-BASIC-SYM-ARC4-002 */
+
+/*!
+ * Compute symmetric encryption
+ *
+ *
+ * @param user_ctx
+ * @param key_info
+ * @param sym_ctx
+ * @param length
+ * @param pt
+ * @param ct
+ *
+ * @return A return code of type #fsl_shw_return_t.
+ */
+fsl_shw_return_t fsl_shw_symmetric_encrypt(fsl_shw_uco_t * user_ctx,
+ fsl_shw_sko_t * key_info,
+ fsl_shw_scco_t * sym_ctx,
+ uint32_t length,
+ const uint8_t * pt, uint8_t * ct)
+{
+ fsl_shw_return_t ret;
+
+ ret = do_symmetric(user_ctx, key_info, sym_ctx, SYM_ENCRYPT,
+ length, pt, ct);
+
+ return ret;
+}
+
+/* PINTFC-API-BASIC-SYM-002 */
+/* PINTFC-API-BASIC-SYM-ARC4-001 */
+/* PINTFC-API-BASIC-SYM-ARC4-002 */
+
+/*!
+ * Compute symmetric decryption
+ *
+ *
+ * @param user_ctx
+ * @param key_info
+ * @param sym_ctx
+ * @param length
+ * @param pt
+ * @param ct
+ *
+ * @return A return code of type #fsl_shw_return_t.
+ */
+fsl_shw_return_t fsl_shw_symmetric_decrypt(fsl_shw_uco_t * user_ctx,
+ fsl_shw_sko_t * key_info,
+ fsl_shw_scco_t * sym_ctx,
+ uint32_t length,
+ const uint8_t * ct, uint8_t * pt)
+{
+ fsl_shw_return_t ret;
+
+ ret = do_symmetric(user_ctx, key_info, sym_ctx, SYM_DECRYPT,
+ length, ct, pt);
+
+ return ret;
+}