/*! * 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) { fsl_shw_return_t status = FSL_RETURN_ERROR_S; uint32_t header; sah_Head_Desc *desc_chain = NULL; sah_Oct_Str ptr1; /* 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 ^ insert_skha_algorithm_arc4; status = add_in_key_desc(header, NULL, 0, key_info, user_ctx->mem_util, &desc_chain); } else { /* load SBox */ /* Desc. #33 w/ARC4 and NO PERMUTE */ header = SAH_HDR_ARC4_SET_MODE_SBOX ^ insert_skha_no_permute ^ insert_skha_algorithm_arc4; status = add_two_in_desc(header, sym_ctx->context, 256, sym_ctx->context + 256, 3, user_ctx->mem_util, &desc_chain); } /* load SBox */ /* Add in-out data descriptor */ if ((status == FSL_RETURN_OK_S) && (length != 0)) { status = add_in_out_desc(SAH_HDR_SKHA_ENC_DEC, in, length, out, length, user_ctx->mem_util, &desc_chain); } /* 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; if (status == FSL_RETURN_OK_S) { status = add_two_out_desc(header, sym_ctx->context, 256, sym_ctx->context + 256, 3, user_ctx->mem_util, &desc_chain); } } } else { /* not ARC4 */ /* Doing 1- or 2- descriptor chain. */ /* Desc. #1 and algorithm and mode */ header = SAH_HDR_SKHA_SET_MODE_IV_KEY ^ insert_skha_mode[sym_ctx->mode] ^ 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 ^= insert_skha_no_key_parity; } /* Header by default is decrypting, so... */ if (encrypt == SYM_ENCRYPT) { header ^= insert_skha_encrypt; } if (sym_ctx->mode == FSL_SYM_MODE_CTR) { header ^= insert_skha_modulus[sym_ctx->modulus_exp]; } if ((sym_ctx->mode == FSL_SYM_MODE_ECB) || (sym_ctx->flags & FSL_SYM_CTX_INIT)) { ptr1 = block_zeros; } else { ptr1 = sym_ctx->context; } status = add_in_key_desc(header, ptr1, sym_ctx->block_size_bytes, key_info, user_ctx->mem_util, &desc_chain); /* Add in-out data descriptor */ if ((length != 0) && (status == FSL_RETURN_OK_S)) { status = add_in_out_desc(SAH_HDR_SKHA_ENC_DEC, in, length, out, length, user_ctx->mem_util, &desc_chain); } /* Unload any desired context */ if ((sym_ctx->flags & FSL_SYM_CTX_SAVE) && (status == FSL_RETURN_OK_S)) { status = add_two_out_desc(SAH_HDR_SKHA_READ_CONTEXT_IV, NULL, 0, sym_ctx->context, sym_ctx->block_size_bytes, user_ctx->mem_util, &desc_chain); } } /* not ARC4 */ if (status != FSL_RETURN_OK_S) { /* Delete possibly-started chain */ sah_Descriptor_Chain_Destroy(user_ctx->mem_util, &desc_chain); } else { status = sah_Descriptor_Chain_Execute(desc_chain, user_ctx); } return status; }
/*! * Get the hmac * * * @param user_ctx Info for acquiring memory * @param key_info * @param hmac_ctx * @param msg * @param length * @param result * @param result_len * * @return A return code of type #fsl_shw_return_t. */ fsl_shw_return_t fsl_shw_hmac( fsl_shw_uco_t* user_ctx, fsl_shw_sko_t* key_info, fsl_shw_hmco_t* hmac_ctx, const uint8_t* msg, uint32_t length, uint8_t* result, uint32_t result_len) { fsl_shw_return_t ret; sah_Head_Desc* desc_chain = NULL; uint32_t header; /* perform sanity check on uco */ ret = sah_validate_uco(user_ctx); /* check flag consistency */ /* Note that Final, Init, and Save are an illegal combination when a key * is being used. Because of the logic flow of this routine, that is * taken care of without being explict */ if (ret == FSL_RETURN_OK_S) { if ( /* nothing to work on */ (((hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) == 0) && ((hmac_ctx->flags & FSL_HMAC_FLAGS_LOAD) == 0)) || /* can't do both */ ((hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) && (hmac_ctx->flags & FSL_HMAC_FLAGS_LOAD)) || /* must be some output */ (((hmac_ctx->flags & FSL_HMAC_FLAGS_SAVE) == 0) && ((hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) == 0))) { ret = FSL_RETURN_BAD_FLAG_S; } } /* build descriptor #6 */ if (ret == FSL_RETURN_OK_S) { /* start building descriptor header */ header = SAH_HDR_MDHA_SET_MODE_MD_KEY ^ insert_mdha_algorithm[hmac_ctx->algorithm] ^ insert_mdha_init; /* if this is to finalize the digest, mark to pad last block */ if (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) { header ^= insert_mdha_pdata; } /*** Check if this is a one shot ***/ if ((hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) && (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE)) { header ^= insert_mdha_hmac; /*** See if this uses Precomputes ***/ if (hmac_ctx->flags & FSL_HMAC_FLAGS_PRECOMPUTES_PRESENT) { ret = add_two_in_desc(header, (uint8_t *)hmac_ctx->inner_precompute, hmac_ctx->context_register_length, (uint8_t *)hmac_ctx->outer_precompute, hmac_ctx->context_length, user_ctx->mem_util, &desc_chain); } else { /*** Precomputes not requested, try using Key ***/ if (key_info->key != NULL) { /* first, validate the key fields and related flag */ if (key_info->key_length == 0) { ret = FSL_RETURN_BAD_KEY_LENGTH_S; } else { if ((key_info->algorithm != FSL_KEY_ALG_HMAC) || (key_info->key_length > 64)) { ret = FSL_RETURN_BAD_ALGORITHM_S; } } if (ret == FSL_RETURN_OK_S) { /* finish building descriptor header (Key specific) */ header ^= insert_mdha_mac_full; ret = add_in_key_desc(header, NULL, 0, key_info, user_ctx->mem_util, &desc_chain); } } else { /*** not using Key or Precomputes, so die ***/ ret = FSL_RETURN_BAD_FLAG_S; } } } else { /*** it's not a one shot, must be multi-step ***/ /* this the last chunk? */ if (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) { header ^= insert_mdha_hmac; ret = add_two_in_desc(header, (uint8_t *)hmac_ctx->ongoing_context, hmac_ctx->context_register_length, (uint8_t *)hmac_ctx->outer_precompute, hmac_ctx->context_length, user_ctx->mem_util, &desc_chain); } else { /* not last chunk */ uint8_t *ptr1; if (hmac_ctx->flags & FSL_HMAC_FLAGS_INIT) { /* must be using precomputes, cannot 'chunk' message * starting with a key */ if (hmac_ctx->flags & FSL_HMAC_FLAGS_PRECOMPUTES_PRESENT) { ptr1 = (uint8_t *)hmac_ctx->inner_precompute; } else { ret = FSL_RETURN_NO_RESOURCE_S; } } else { ptr1 = (uint8_t *)hmac_ctx->ongoing_context; } if (ret == FSL_RETURN_OK_S) { ret = add_two_in_desc(header, ptr1, hmac_ctx->context_register_length, NULL, 0, user_ctx->mem_util, &desc_chain); } } } } /* end of building descriptor #6 */ /*** build descriptor #10 & maybe 11 ***/ if (ret == FSL_RETURN_OK_S) { header = SAH_HDR_MDHA_HASH; if (hmac_ctx->flags & FSL_HMAC_FLAGS_FINALIZE) { /* check that the results parameters seem reasonable */ if ((result_len != 0) && (result != NULL)) { if (result_len > hmac_ctx->context_register_length) { result_len = hmac_ctx->context_register_length; } /* message in / digest out (descriptor #10) */ ret = add_in_out_desc(header, msg, length, result, result_len, user_ctx->mem_util, &desc_chain); /*** see if descriptor #11 needs to be built ***/ if ((hmac_ctx->flags & FSL_HMAC_FLAGS_SAVE) && (ret == FSL_RETURN_OK_S)) { header = SAH_HDR_MDHA_STORE_DIGEST; /* nothing in / context out */ ret = add_two_in_desc(header, NULL, 0, (uint8_t *)hmac_ctx->ongoing_context, hmac_ctx->context_register_length, user_ctx->mem_util, &desc_chain); } } else { /* something wrong with result or its length */ ret = FSL_RETURN_BAD_DATA_LENGTH_S; } } else { /* finalize not set, so store in ongoing context field */ if ((length % 64) == 0) { /* message in / context out */ ret = add_in_out_desc(header, msg, length, (uint8_t *)hmac_ctx->ongoing_context, hmac_ctx->context_register_length, user_ctx->mem_util, &desc_chain); } else { ret = FSL_RETURN_BAD_DATA_LENGTH_S; } } } /* Pass the chain to the driver. */ if (ret == FSL_RETURN_OK_S) { ret = sah_Descriptor_Chain_Execute(desc_chain, user_ctx); } else { if (desc_chain != NULL) { /* ignore the destroy function's return value, the destroy * function's return value is not what went wroung with this * routine */ sah_Descriptor_Chain_Destroy(user_ctx->mem_util, &desc_chain); } } return ret; }