Logo Search packages:      
Sourcecode: linux-fsl-imx51 version File versions  Download package

fsl_shw_sym.c

/*
 * Copyright 2004-2007 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.
 */
00238 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.
 */
00269 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;
}

Generated by  Doxygen 1.6.0   Back to index