/*! * Create two links using keys allocated in the scc * * @param header The Sahara header value for the descriptor. * @param in1 The first input buffer (or NULL) * @param in1_length Size of @a in1 * @param[out] in2 The second input buffer (or NULL) * @param in2_length Size of @a in2 * @param mu Memory functions * @param[in,out] desc_chain Chain to start or append to * * @return A return code of type #fsl_shw_return_t. */ fsl_shw_return_t add_key_key_desc(uint32_t header, fsl_shw_sko_t * key_info1, fsl_shw_sko_t * key_info2, const sah_Mem_Util * mu, sah_Head_Desc ** desc_chain) { fsl_shw_return_t status; sah_Link *link1 = NULL; sah_Link *link2 = NULL; status = sah_Create_Key_Link(mu, &link1, key_info1); if (status == FSL_RETURN_OK_S) { status = sah_Create_Key_Link(mu, &link2, key_info2); } if (status != FSL_RETURN_OK_S) { if (link1 != NULL) { sah_Destroy_Link(mu, link1); } if (link2 != NULL) { sah_Destroy_Link(mu, link2); } } else { status = sah_Append_Desc(mu, desc_chain, header, link1, link2); } return status; }
/*! * Add descriptor where link1 is input buffer, link2 is output buffer. * * @param header The Sahara header value for the descriptor. * @param in The input buffer * @param in_length Size of the input buffer * @param[out] out The output buffer * @param out_length Size of the output buffer * @param mu Memory functions * @param[in,out] desc_chain Chain to start or append to * * @return A return code of type #fsl_shw_return_t. */ fsl_shw_return_t add_in_out_desc(uint32_t header, const uint8_t * in, uint32_t in_length, uint8_t * out, uint32_t out_length, const sah_Mem_Util * mu, sah_Head_Desc ** desc_chain) { fsl_shw_return_t status = FSL_RETURN_OK_S; sah_Link *link1 = NULL; sah_Link *link2 = NULL; if (in != NULL) { status = sah_Create_Link(mu, &link1, (sah_Oct_Str) in, in_length, SAH_USES_LINK_DATA); } if ((status == FSL_RETURN_OK_S) && (out != NULL)) { status = sah_Create_Link(mu, &link2, (sah_Oct_Str) out, out_length, SAH_OUTPUT_LINK | SAH_USES_LINK_DATA); } if (status != FSL_RETURN_OK_S) { if (link1 != NULL) { sah_Destroy_Link(mu, link1); } if (link2 != NULL) { sah_Destroy_Link(mu, link2); } } else { status = sah_Append_Desc(mu, desc_chain, header, link1, link2); } return status; }
/*! * Add descriptor where both links are inputs, the second one being a key. * * @param header The Sahara header value for the descriptor. * @param in1 The first input buffer (or NULL) * @param in1_length Size of @a in1 * @param[out] in2 The second input buffer (or NULL) * @param in2_length Size of @a in2 * @param mu Memory functions * @param[in,out] desc_chain Chain to start or append to * * @return A return code of type #fsl_shw_return_t. */ fsl_shw_return_t add_in_key_desc(uint32_t header, const uint8_t * in1, uint32_t in1_length, fsl_shw_sko_t * key_info, const sah_Mem_Util * mu, sah_Head_Desc ** desc_chain) { fsl_shw_return_t status = FSL_RETURN_OK_S; sah_Link *link1 = NULL; sah_Link *link2 = NULL; if (in1 != NULL) { status = sah_Create_Link(mu, &link1, (sah_Oct_Str) in1, in1_length, SAH_USES_LINK_DATA); } if (status == FSL_RETURN_OK_S) { status = sah_Create_Key_Link(mu, &link2, key_info); } if (status != FSL_RETURN_OK_S) { if (link1 != NULL) { sah_Destroy_Link(mu, link1); } if (link2 != NULL) { sah_Destroy_Link(mu, link2); } } else { status = sah_Append_Desc(mu, desc_chain, header, link1, link2); } return status; }
/*! * Releases the memory allocated by the Security Function library for * descriptors, links and any internally allocated memory referenced in the * given chain. Note that memory allocated by user applications is not * released. * * @post The @a desc_head pointer will be set to NULL to prevent further use. * * @brief Destroy a descriptor chain and free memory of associated links * * @param mu Memory functions * @param desc_head Pointer to head of descriptor chain to be freed * * @return none */ void sah_Descriptor_Chain_Destroy(const sah_Mem_Util * mu, sah_Head_Desc ** desc_head) { sah_Desc *desc_ptr = &(*desc_head)->desc; sah_Head_Desc *desc_head_ptr = (sah_Head_Desc *) desc_ptr; while (desc_ptr != NULL) { register sah_Desc *next_desc_ptr; if (desc_ptr->ptr1 != NULL) { sah_Destroy_Link(mu, desc_ptr->ptr1); } if (desc_ptr->ptr2 != NULL) { sah_Destroy_Link(mu, desc_ptr->ptr2); } next_desc_ptr = desc_ptr->next; /* Be sure to free head descriptor as such */ if (desc_ptr == (sah_Desc *) desc_head_ptr) { mu->mu_free_head_desc(mu->mu_ref, desc_head_ptr); } else { mu->mu_free_desc(mu->mu_ref, desc_ptr); } desc_ptr = next_desc_ptr; } *desc_head = NULL; }
/*! * Add a Descriptor which will process with CBC the NIST preamble data * * @param desc_chain Current chain * @param user_ctx User's context * @param auth_ctx Inf * @param auth_data Additional auth data for this call * @param auth_data_length Length in bytes of @a auth_data * * @return A return code of type #fsl_shw_return_t. */ static inline fsl_shw_return_t add_assoc_preamble(sah_Head_Desc ** desc_chain, fsl_shw_uco_t * user_ctx, fsl_shw_acco_t * auth_ctx, const uint8_t * auth_data, uint32_t auth_data_length) { uint8_t *temp_buf; sah_Link *link1 = NULL; sah_Link *link2 = NULL; fsl_shw_return_t status = FSL_RETURN_OK_S; uint32_t cbc_data_length = 0; /* Assume AES */ uint32_t header = SAH_HDR_SKHA_ENC_DEC; /* Grab a block big enough for multiple uses so that only one allocate * request needs to be made. */ temp_buf = user_ctx->mem_util->mu_malloc(user_ctx->mem_util->mu_ref, 3 * auth_ctx->auth_info.CCM_ctx_info. block_size_bytes); if (temp_buf == NULL) { status = FSL_RETURN_NO_RESOURCE_S; } else { uint32_t temp_buf_flag; if (auth_ctx->flags & FSL_ACCO_NIST_CCM) { status = process_assoc_from_nist_params(&link1, &cbc_data_length, user_ctx, auth_ctx, auth_data, auth_data_length, &temp_buf); /* temp_buf has been referenced (and incremented). Only 'own' it * once, at its first value. Since the nist routine called above * bumps it... */ temp_buf_flag = SAH_USES_LINK_DATA; } else { /* if NIST */ if (status == FSL_RETURN_OK_S) { status = sah_Create_Link(user_ctx->mem_util, &link1, (uint8_t *) auth_data, auth_data_length, SAH_USES_LINK_DATA); /* for next/first use of temp_buf */ temp_buf_flag = SAH_OWNS_LINK_DATA; } cbc_data_length = auth_data_length; } /* else not NIST */ /* * Auth data links have been created. Now create link for the * useless output of the CBC calculation. */ if (status == FSL_RETURN_OK_S) { status = sah_Create_Link(user_ctx->mem_util, &link2, temp_buf, auth_ctx->auth_info. CCM_ctx_info.block_size_bytes, temp_buf_flag | SAH_OUTPUT_LINK); } temp_buf += auth_ctx->auth_info.CCM_ctx_info.block_size_bytes; cbc_data_length -= auth_ctx->auth_info.CCM_ctx_info.block_size_bytes; if (cbc_data_length != 0) { while ((status == FSL_RETURN_OK_S) && (cbc_data_length != 0)) { uint32_t linklen = (cbc_data_length > CBC_BUF_LEN) ? CBC_BUF_LEN : cbc_data_length; status = sah_Append_Link(user_ctx->mem_util, link2, cbc_buffer, linklen, SAH_USES_LINK_DATA | SAH_OUTPUT_LINK); cbc_data_length -= linklen; } } if (status != FSL_RETURN_OK_S) { if (link1 != NULL) { sah_Destroy_Link(user_ctx->mem_util, link1); } if (link2 != NULL) { sah_Destroy_Link(user_ctx->mem_util, link2); } } else { /* Header to set up crank through auth data */ status = sah_Append_Desc(user_ctx->mem_util, desc_chain, header, link1, link2); } } return status; }
/*! * Create and populate a single descriptor * * The pointer and length fields will be be set based on the chains passed in * as @a link1 and @a link2. * * @param mu Memory utility suite * @param desc Location to store pointer of new descriptor * @param head_desc Non-zero if this will be first in chain; zero otherwise * @param header The Sahara header value to store in the descriptor * @param link1 A value (or NULL) for the first ptr * @param link2 A value (or NULL) for the second ptr * * @post If allocation succeeded, the @a link1 and @link2 will be linked into * the descriptor. If allocation failed, those link structues will be * freed, and the @a desc will be unchanged. * * @return A return code of type #fsl_shw_return_t. */ static fsl_shw_return_t sah_Create_Desc(const sah_Mem_Util * mu, sah_Desc ** desc, int head_desc, uint32_t header, sah_Link * link1, sah_Link * link2) { fsl_shw_return_t status = FSL_RETURN_NO_RESOURCE_S; #ifdef DIAG_SECURITY_FUNC char diag[50]; #endif /*DIAG_SECURITY_FUNC */ if (head_desc != 0) { *desc = (sah_Desc *) mu->mu_alloc_head_desc(mu->mu_ref); } else { *desc = mu->mu_alloc_desc(mu->mu_ref); } /* populate descriptor if memory allocation successful */ if ((*desc) != NULL) { sah_Link *temp_link; status = FSL_RETURN_OK_S; (*desc)->header = header; temp_link = (*desc)->ptr1 = link1; (*desc)->len1 = 0; while (temp_link != NULL) { (*desc)->len1 += temp_link->len; temp_link = temp_link->next; } temp_link = (*desc)->ptr2 = link2; (*desc)->len2 = 0; while (temp_link != NULL) { (*desc)->len2 += temp_link->len; temp_link = temp_link->next; } (*desc)->next = NULL; #ifdef DIAG_SECURITY_FUNC LOG_DIAG("Created Desc"); LOG_DIAG("------------"); sprintf(diag, " address = 0x%x", (int)*desc); LOG_DIAG(diag); sprintf(diag, " desc->header = 0x%x", (*desc)->header); LOG_DIAG(diag); sprintf(diag, " desc->len1 = %d", (*desc)->len1); LOG_DIAG(diag); sprintf(diag, " desc->ptr1 = 0x%x", (int)((*desc)->ptr1)); LOG_DIAG(diag); sprintf(diag, " desc->len2 = %d", (*desc)->len2); LOG_DIAG(diag); sprintf(diag, " desc->ptr2 = 0x%x", (int)((*desc)->ptr2)); LOG_DIAG(diag); sprintf(diag, " desc->next = 0x%x", (int)((*desc)->next)); LOG_DIAG(diag); #endif /*DIAG_SECURITY_FUNC */ } else { #ifdef DIAG_SECURITY_FUNC LOG_DIAG("Allocation of memory for sah_Desc failed!\n"); #endif /*DIAG_SECURITY_FUNC */ /* Destroy the links, otherwise the memory allocated by the Security Function layer for the links (and possibly the data within the links) will be lost */ if (link1 != NULL) { sah_Destroy_Link(mu, link1); } if (link2 != NULL) { sah_Destroy_Link(mu, link2); } } return status; }
/*! * Insert descriptors to calculate ICV = HMAC(key=T, data=LEN|ALG|KEY') * * @param user_ctx User's context for this operation * @param desc_chain Descriptor chain to append to * @param t_key_info T's key object * @param black_key Beginning of Black Key region * @param key_length Number of bytes of key' there are in @c black_key * @param[out] hmac Location to store ICV. Will be tagged "USES" so * sf routines will not try to free it. * * @return A return code of type #fsl_shw_return_t. */ static inline fsl_shw_return_t create_icv_calc(fsl_shw_uco_t * user_ctx, sah_Head_Desc ** desc_chain, fsl_shw_sko_t * t_key_info, const uint8_t * black_key, uint32_t key_length, uint8_t * hmac) { fsl_shw_return_t sah_code; uint32_t header; sah_Link *link1 = NULL; sah_Link *link2 = NULL; /* Load up T as key for the HMAC */ header = (SAH_HDR_MDHA_SET_MODE_MD_KEY /* #6 */ ^ sah_insert_mdha_algorithm_sha256 ^ sah_insert_mdha_init ^ sah_insert_mdha_hmac ^ sah_insert_mdha_pdata ^ sah_insert_mdha_mac_full); sah_code = sah_add_in_key_desc(header, NULL, 0, t_key_info, /* Reference T in RED */ user_ctx->mem_util, desc_chain); if (sah_code != FSL_RETURN_OK_S) { goto out; } /* Previous step loaded key; Now set up to hash the data */ header = SAH_HDR_MDHA_HASH; /* #10 */ /* Input - start with ownerid */ sah_code = sah_Create_Link(user_ctx->mem_util, &link1, (void *)&t_key_info->userid, sizeof(t_key_info->userid), SAH_USES_LINK_DATA); if (sah_code != FSL_RETURN_OK_S) { goto out; } /* Still input - Append black-key fields len, alg, key' */ sah_code = sah_Append_Link(user_ctx->mem_util, link1, (void *)black_key + LENGTH_OFFSET, (LENGTH_LENGTH + ALGORITHM_LENGTH + key_length), SAH_USES_LINK_DATA); if (sah_code != FSL_RETURN_OK_S) { goto out; } /* Output - computed ICV/HMAC */ sah_code = sah_Create_Link(user_ctx->mem_util, &link2, hmac, ICV_LENGTH, SAH_USES_LINK_DATA | SAH_OUTPUT_LINK); if (sah_code != FSL_RETURN_OK_S) { goto out; } sah_code = sah_Append_Desc(user_ctx->mem_util, desc_chain, header, link1, link2); out: if (sah_code != FSL_RETURN_OK_S) { (void)sah_Destroy_Link(user_ctx->mem_util, link1); (void)sah_Destroy_Link(user_ctx->mem_util, link2); } return sah_code; } /* create_icv_calc */
/*! * 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; }