Пример #1
0
/*
 * 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;

	/* Load up T as key for the HMAC */
	header = (SAH_HDR_MDHA_SET_MODE_MD_KEY	/* #6 */
		  ^ insert_mdha_algorithm_sha1
		  ^ insert_mdha_init ^ insert_mdha_hmac ^ insert_mdha_pdata
		  ^ insert_mdha_mac_full);
	sah_code = add_in_key_desc(header, NULL, 0, t_key_info,	/* Reference T in RED */
				   user_ctx->mem_util, desc_chain);

	/* Previous step loaded key; Now set up to hash the data */
	if (sah_code == FSL_RETURN_OK_S) {
		sah_Link *link1 = NULL;
		sah_Link *link2 = NULL;
		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) {
			/* 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) {
				link1 = NULL;
			} else {
				/* Output - computed ICV/HMAC */
				sah_code =
				    sah_Create_Link(user_ctx->mem_util, &link2,
						    hmac, ICV_LENGTH,
						    SAH_USES_LINK_DATA |
						    SAH_OUTPUT_LINK);
			}

			sah_code =
			    sah_Append_Desc(user_ctx->mem_util, desc_chain,
					    header, link1, link2);
		}
	}

	return sah_code;
}				/* create_icv_calc */
Пример #2
0
/*!
 * Perform wrapping of a black key from a RED slot
 *
 * @param      user_ctx         A user context from #fsl_shw_register_user().
 * @param[in,out] key_info      The information about the key to be which will
 *                              be wrapped... key length, slot info, etc.
 * @param      black_key        Place to store encrypted key
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
static fsl_shw_return_t wrap(fsl_shw_uco_t * user_ctx,
			     fsl_shw_sko_t * key_info, uint8_t * black_key)
{
	fsl_shw_return_t ret;
	sah_Head_Desc *desc_chain = NULL;
	unsigned slots_allocated = 0;	/* boolean */
	fsl_shw_sko_t T_key_info;	/* for holding T */
	fsl_shw_sko_t KEK_key_info;	/* for holding KEK */

	black_key[LENGTH_OFFSET] = key_info->key_length;
	black_key[ALGORITHM_OFFSET] = key_info->algorithm;

	memcpy(&T_key_info, key_info, sizeof(T_key_info));
	fsl_shw_sko_set_key_length(&T_key_info, T_LENGTH);
	T_key_info.algorithm = FSL_KEY_ALG_HMAC;

	memcpy(&KEK_key_info, &T_key_info, sizeof(KEK_key_info));
	KEK_key_info.algorithm = FSL_KEY_ALG_AES;

	ret = do_scc_slot_alloc(user_ctx, T_LENGTH, key_info->userid,
				&T_key_info.handle);

	if (ret == FSL_RETURN_OK_S) {
		ret = do_scc_slot_alloc(user_ctx, KEK_LENGTH, key_info->userid,
					&KEK_key_info.handle);
		if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
			LOG_DIAG("do_scc_slot_alloc() failed");
#endif
			do_scc_slot_dealloc(user_ctx, key_info->userid,
					    T_key_info.handle);
		} else {
			slots_allocated = 1;
		}

	}

	/* Set up to compute everything except T' ... */
	if (ret == FSL_RETURN_OK_S) {
		uint32_t header;

#ifndef DO_REPEATABLE_WRAP
		/* Compute T = RND() */
		header = SAH_HDR_RNG_GENERATE;	/* Desc. #18 */
		ret = add_key_out_desc(header, &T_key_info, NULL, 0,
				       user_ctx->mem_util, &desc_chain);
#else
		ret = do_scc_slot_load_slot(user_ctx, T_key_info.userid,
					    T_key_info.handle, T_block,
					    T_key_info.key_length);
#endif

		/* Compute KEK = SHA1(T | Ownerid) */
		if (ret == FSL_RETURN_OK_S) {
			sah_Link *link1;
			sah_Link *link2;

			header = (SAH_HDR_MDHA_SET_MODE_HASH	/* #8 */
				  ^ insert_mdha_init
				  ^ insert_mdha_algorithm[FSL_HASH_ALG_SHA1]
				  ^ insert_mdha_pdata);

			/* Input - Start with T */
			ret =
			    sah_Create_Key_Link(user_ctx->mem_util, &link1,
						&T_key_info);

			if (ret == FSL_RETURN_OK_S) {
				/* Still input - append ownerid */
				ret = sah_Append_Link(user_ctx->mem_util, link1,
						      (void *)&key_info->userid,
						      sizeof(key_info->userid),
						      SAH_USES_LINK_DATA);
			}

			if (ret == FSL_RETURN_OK_S) {
				/* Output - KEK goes into RED slot */
				ret =
				    sah_Create_Key_Link(user_ctx->mem_util,
							&link2, &KEK_key_info);
			}

			/* Put the Hash calculation into the chain. */
			if (ret == FSL_RETURN_OK_S) {
				ret =
				    sah_Append_Desc(user_ctx->mem_util,
						    &desc_chain, header, link1,
						    link2);
			}
		}

		/* Compute KEY' = AES-encrypt(KEK, KEY) */
		if (ret == FSL_RETURN_OK_S) {

			header = (SAH_HDR_SKHA_SET_MODE_IV_KEY	/* #1 */
				  ^ insert_skha_mode[FSL_SYM_MODE_CTR]
				  ^ insert_skha_algorithm[FSL_KEY_ALG_AES]
				  ^ insert_skha_modulus[FSL_CTR_MOD_128]);
			/* Set up KEK as key to use */
			ret = add_in_key_desc(header, NULL, 0, &KEK_key_info,
					      user_ctx->mem_util, &desc_chain);

			/* Set up KEY as input, KEY' as output */
			if (ret == FSL_RETURN_OK_S) {
				header = SAH_HDR_SKHA_ENC_DEC;	/* #4 */
				ret = add_key_out_desc(header, key_info,
						       black_key +
						       KEY_PRIME_OFFSET,
						       key_info->key_length,
						       user_ctx->mem_util,
						       &desc_chain);
			}
#ifdef DIAG_SECURITY_FUNC
			if (ret != FSL_RETURN_OK_S) {
				LOG_DIAG
				    ("Creation of sah_Key_Link failed due to bad key"
				     " flag!\n");
			}
#endif				/*DIAG_SECURITY_FUNC */
		}

		/* Compute and store ICV into Black Key */
		if (ret == FSL_RETURN_OK_S) {
			ret =
			    create_icv_calc(user_ctx, &desc_chain, &T_key_info,
					    black_key, key_info->key_length,
					    black_key + ICV_OFFSET);
#ifdef DIAG_SECURITY_FUNC
			if (ret != FSL_RETURN_OK_S) {
				LOG_DIAG
				    ("Creation of sah_Key_Link failed due to bad key"
				     " flag!\n");
			}
#endif				/*DIAG_SECURITY_FUNC */
		}
	}

	/* Now get Sahara to do the work. */
	if (ret == FSL_RETURN_OK_S) {
		ret = sah_Descriptor_Chain_Execute(desc_chain, user_ctx);
#ifdef DIAG_SECURITY_FUNC
		if (ret != FSL_RETURN_OK_S) {
			LOG_DIAG("sah_Descriptor_Chain_Execute() failed");
		}
#endif
	}

	/* Compute T' = SLID_encrypt(T); Result goes to Black Key */
	if (ret == FSL_RETURN_OK_S) {
		ret = do_scc_slot_encrypt(user_ctx, T_key_info.userid,
					  T_key_info.handle,
					  T_LENGTH, black_key + T_PRIME_OFFSET);
#ifdef DIAG_SECURITY_FUNC
		if (ret != FSL_RETURN_OK_S) {
			LOG_DIAG("do_scc_slot_encrypt() failed");
		}
#endif
	}

	if (slots_allocated) {
		do_scc_slot_dealloc(user_ctx, key_info->userid,
				    T_key_info.handle);
		do_scc_slot_dealloc(user_ctx, key_info->userid,
				    KEK_key_info.handle);
	}

	return ret;
}				/* wrap */
Пример #3
0
/*!
 * Perform unwrapping of a black key into a RED slot
 *
 * @param         user_ctx      A user context from #fsl_shw_register_user().
 * @param[in,out] key_info      The information about the key to be which will
 *                              be unwrapped... key length, slot info, etc.
 * @param         black_key     Encrypted key
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
static fsl_shw_return_t unwrap(fsl_shw_uco_t * user_ctx,
			       fsl_shw_sko_t * key_info,
			       const uint8_t * black_key)
{
	fsl_shw_return_t ret = FSL_RETURN_ERROR_S;
	sah_Mem_Util *mu = user_ctx->mem_util;
	uint8_t *hmac = mu->mu_malloc(mu->mu_ref, ICV_LENGTH);

	if (hmac == NULL) {
		ret = FSL_RETURN_NO_RESOURCE_S;
	} else {
		sah_Head_Desc *desc_chain = NULL;
		fsl_shw_sko_t t_key_info;
		unsigned i;

		/* Set up key_info for "T" - use same slot as eventual key */
		fsl_shw_sko_init(&t_key_info, FSL_KEY_ALG_AES);
		t_key_info.userid = key_info->userid;
		t_key_info.handle = key_info->handle;
		t_key_info.flags = key_info->flags;
		t_key_info.key_length = T_LENGTH;

		/* Compute T = SLID_decrypt(T'); leave in RED slot */
		ret = do_scc_slot_decrypt(user_ctx, key_info->userid,
					  t_key_info.handle,
					  T_LENGTH, black_key + T_PRIME_OFFSET);

		/* Compute ICV = HMAC(T, ownerid | len | alg | key' */
		if (ret == FSL_RETURN_OK_S) {
			ret =
			    create_icv_calc(user_ctx, &desc_chain, &t_key_info,
					    black_key, key_info->key_length,
					    hmac);
			if (ret == FSL_RETURN_OK_S) {
				ret =
				    sah_Descriptor_Chain_Execute(desc_chain,
								 user_ctx);
				desc_chain = NULL;
			}
#ifdef DIAG_SECURITY_FUNC
			else {
				LOG_DIAG
				    ("Creation of sah_Key_Link failed due to bad key"
				     " flag!\n");
			}
#endif				/*DIAG_SECURITY_FUNC */

			/* Check computed ICV against value in Black Key */
			if (ret == FSL_RETURN_OK_S) {
				for (i = 0; i < ICV_LENGTH; i++) {
					if (black_key[ICV_OFFSET + i] !=
					    hmac[i]) {
						ret = FSL_RETURN_AUTH_FAILED_S;
						break;
					}
				}
			}

			/* This is no longer needed. */
			mu->mu_free(mu->mu_ref, hmac);

			/* Compute KEK = SHA1(T | ownerid).  Rewrite slot with value */
			if (ret == FSL_RETURN_OK_S) {
				sah_Link *link1 = NULL;
				sah_Link *link2 = NULL;
				uint32_t header;

				header = (SAH_HDR_MDHA_SET_MODE_HASH	/* #8 */
					  ^ insert_mdha_init
					  ^ insert_mdha_algorithm_sha1
					  ^ insert_mdha_pdata);

				/* Input - Start with T */
				ret =
				    sah_Create_Key_Link(user_ctx->mem_util,
							&link1, &t_key_info);

				if (ret == FSL_RETURN_OK_S) {
					/* Still input - append ownerid */
					ret =
					    sah_Append_Link(user_ctx->mem_util,
							    link1,
							    (void *)&key_info->
							    userid,
							    sizeof(key_info->
								   userid),
							    SAH_USES_LINK_DATA);
				}

				if (ret == FSL_RETURN_OK_S) {
					/* Output - KEK goes into RED slot */
					ret =
					    sah_Create_Key_Link(user_ctx->
								mem_util,
								&link2,
								&t_key_info);
				}

				if (ret == FSL_RETURN_OK_S) {
					/* Put the Hash calculation into the chain. */
					ret =
					    sah_Append_Desc(user_ctx->mem_util,
							    &desc_chain, header,
							    link1, link2);
				}
			}

			/* Compute KEY = AES-decrypt(KEK, KEY') */
			if (ret == FSL_RETURN_OK_S) {
				uint32_t header;
				unsigned rounded_key_length;
				unsigned original_key_length =
				    key_info->key_length;

				header = (SAH_HDR_SKHA_SET_MODE_IV_KEY	/* #1 */
					  ^ insert_skha_mode_ctr
					  ^ insert_skha_algorithm_aes
					  ^ insert_skha_modulus_128);
				/* Load KEK in as the key to use */
				ret =
				    add_in_key_desc(header, NULL, 0,
						    &t_key_info,
						    user_ctx->mem_util,
						    &desc_chain);

				/* Make sure that KEY = AES(KEK, KEY') step writes a multiple
				   of words into the SCC to avoid 'Byte Access errors.' */
				if ((original_key_length & 3) != 0) {
					rounded_key_length =
					    original_key_length + 4 -
					    (original_key_length & 3);
				} else {
					rounded_key_length =
					    original_key_length;
				}

				key_info->key_length = rounded_key_length;
				if (ret == FSL_RETURN_OK_S) {
					/* Now set up for computation.  Result in RED */
					header = SAH_HDR_SKHA_ENC_DEC;	/* #4 */

					ret =
					    add_in_key_desc(header,
							    black_key +
							    KEY_PRIME_OFFSET,
							    rounded_key_length,
							    key_info,
							    user_ctx->mem_util,
							    &desc_chain);
					key_info->key_length =
					    original_key_length;
					/* Perform the operation */
					if (ret == FSL_RETURN_OK_S) {
						ret =
						    sah_Descriptor_Chain_Execute
						    (desc_chain, user_ctx);
					}
				}
			}

			/* Erase tracks */
			t_key_info.userid = 0xdeadbeef;
			t_key_info.handle = 0xdeadbeef;
		}
	}

	return ret;
}				/* unwrap */
Пример #4
0
/*!
 * 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;
}
Пример #5
0
/*!
 * Append a descriptor chain which will compute CBC over the
 * formatted associated data blocks.
 *
 * @param[in,out] link1       Where to append the new link
 * @param[in,out] data_len    Location of current/updated auth-only data length
 * @param         user_ctx    Info for acquiring memory
 * @param         auth_ctx    Location of block0 value
 * @param         auth_data   Unformatted associated data
 * @param         auth_data_length Length in octets of @a auth_data
 * @param[in,out] temp_buf    Location of in-process data.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
static inline fsl_shw_return_t process_assoc_from_nist_params(sah_Link ** link1,
							      uint32_t *
							      data_len,
							      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)
{
	fsl_shw_return_t status;
	uint32_t auth_size_length =
	    COMPUTE_NIST_AUTH_LEN_SIZE(auth_data_length);
	uint32_t auth_pad_length =
	    auth_ctx->auth_info.CCM_ctx_info.block_size_bytes -
	    (auth_data_length +
	     auth_size_length) %
	    auth_ctx->auth_info.CCM_ctx_info.block_size_bytes;

	if (auth_pad_length ==
	    auth_ctx->auth_info.CCM_ctx_info.block_size_bytes) {
		auth_pad_length = 0;
	}

	/* Put in Block0 */
	status = sah_Create_Link(user_ctx->mem_util, link1,
				 auth_ctx->auth_info.CCM_ctx_info.context,
				 auth_ctx->auth_info.CCM_ctx_info.
				 block_size_bytes, SAH_USES_LINK_DATA);

	if (status == FSL_RETURN_OK_S) {
		/* Add on length preamble to auth data */
		STORE_NIST_AUTH_LEN(auth_data_length, *temp_buf);
		status = sah_Append_Link(user_ctx->mem_util, *link1,
					 *temp_buf, auth_size_length,
					 SAH_OWNS_LINK_DATA);
		*temp_buf += auth_size_length;	/* 2, 6, or 10 bytes */
	}

	if (status == FSL_RETURN_OK_S) {
		/* Add in auth data */
		status = sah_Append_Link(user_ctx->mem_util, *link1,
					 (uint8_t *) auth_data,
					 auth_data_length, SAH_USES_LINK_DATA);
	}

	if ((status == FSL_RETURN_OK_S) && (auth_pad_length > 0)) {
		status = sah_Append_Link(user_ctx->mem_util, *link1,
					 block_zeros, auth_pad_length,
					 SAH_USES_LINK_DATA);
	}

	*data_len = auth_ctx->auth_info.CCM_ctx_info.block_size_bytes +
	    auth_data_length + auth_size_length + auth_pad_length;

	return status;
}
/*!
 * Perform wrapping of a black key from a RED slot
 *
 * @param      user_ctx         A user context from #fsl_shw_register_user().
 * @param[in,out] key_info      The information about the key to be which will
 *                              be wrapped... key length, slot info, etc.
 * @param      black_key        Place to store encrypted key
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
static fsl_shw_return_t wrap(fsl_shw_uco_t * user_ctx,
			     fsl_shw_sko_t * key_info, uint8_t * black_key)
{
	SAH_SF_DCLS;
	unsigned slots_allocated = 0;	/* boolean */
	fsl_shw_sko_t T_key_info;	/* for holding T */
	fsl_shw_sko_t KEK_key_info;	/* for holding KEK */
	unsigned original_key_length = key_info->key_length;
	unsigned rounded_key_length;
	sah_Link *link1;
	sah_Link *link2;

	black_key[LENGTH_OFFSET] = key_info->key_length;
	black_key[ALGORITHM_OFFSET] = key_info->algorithm;

	memcpy(&T_key_info, key_info, sizeof(T_key_info));
	fsl_shw_sko_set_key_length(&T_key_info, T_LENGTH);
	T_key_info.algorithm = FSL_KEY_ALG_HMAC;

	memcpy(&KEK_key_info, &T_key_info, sizeof(KEK_key_info));
	KEK_key_info.algorithm = FSL_KEY_ALG_AES;

	if (key_info->keystore == NULL) {
		/* Key goes in system keystore */
		ret = do_system_keystore_slot_alloc(user_ctx,
				T_LENGTH, key_info->userid,
			    &T_key_info.handle);
	
	} else {
		/* Key goes in user keystore */
		ret = keystore_slot_alloc(key_info->keystore,
				  T_LENGTH,
				  key_info->userid, &T_key_info.handle);
	}
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	if (key_info->keystore == NULL) {
		/* Key goes in system keystore */
		ret = do_system_keystore_slot_alloc(user_ctx,
				KEK_LENGTH, key_info->userid,
				&KEK_key_info.handle);
		
	} else {
		/* Key goes in user keystore */
		ret = keystore_slot_alloc(key_info->keystore,
			  KEK_LENGTH,  key_info->userid, 
			  &KEK_key_info.handle);
	}

	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("do_scc_slot_alloc() failed");
#endif
		if (key_info->keystore == NULL) {
			/* Key goes in system keystore */
			(void)do_system_keystore_slot_dealloc(user_ctx,
				key_info->userid, T_key_info.handle);
	
		} else {
			/* Key goes in user keystore */
			(void)keystore_slot_dealloc(key_info->keystore,
				  	key_info->userid, T_key_info.handle);
		}
	} else {
		slots_allocated = 1;
	}

	/* Set up to compute everything except T' ... */
#ifndef DO_REPEATABLE_WRAP
	/* Compute T = RND() */
	header = SAH_HDR_RNG_GENERATE;	/* Desc. #18 */
	DESC_KEY_OUT(header, &T_key_info, 0, NULL);
#else
	if (key_info->keystore == NULL) {
		/* Key goes in system keystore */
		ret = do_system_keystore_slot_load(user_ctx,
			   T_key_info.userid,
			   T_key_info.handle, T_block,
			   T_key_info.key_length);
	} else {
		/* Key goes in user keystore */
		ret = keystore_slot_load(key_info->keystore,
				 T_key_info.userid,
				 T_key_info.handle,
				 T_block, T_key_info.key_length);
	}

	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
#endif

	/* Compute KEK = SHA256(T | Ownerid) */
	header = (SAH_HDR_MDHA_SET_MODE_HASH	/* #8 */
		  ^ sah_insert_mdha_init
		  ^ sah_insert_mdha_algorithm[FSL_HASH_ALG_SHA256]
		  ^ sah_insert_mdha_pdata);
	/* Input - Start with T */
	ret = sah_Create_Key_Link(user_ctx->mem_util, &link1, &T_key_info);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
	/* Still input - append ownerid */
	ret = sah_Append_Link(user_ctx->mem_util, link1,
			      (void *)&key_info->userid,
			      sizeof(key_info->userid), SAH_USES_LINK_DATA);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
	/* Output - KEK goes into RED slot */
	ret = sah_Create_Key_Link(user_ctx->mem_util, &link2, &KEK_key_info);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
	/* Put the Hash calculation into the chain. */
	ret = sah_Append_Desc(user_ctx->mem_util, &desc_chain,
			      header, link1, link2);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
#if defined(NEED_CTR_WORKAROUND)
	rounded_key_length = ROUND_LENGTH(original_key_length);
	key_info->key_length = rounded_key_length;
#else
	rounded_key_length = original_key_length;
#endif
	/* Compute KEY' = AES-encrypt(KEK, KEY) */
	header = (SAH_HDR_SKHA_SET_MODE_IV_KEY	/* #1 */
		  ^ sah_insert_skha_mode[FSL_SYM_MODE_CTR]
		  ^ sah_insert_skha_algorithm[FSL_KEY_ALG_AES]
		  ^ sah_insert_skha_modulus[FSL_CTR_MOD_128]);
	/* Set up KEK as key to use */
	DESC_IN_KEY(header, 0, NULL, &KEK_key_info);
	header = SAH_HDR_SKHA_ENC_DEC;
	DESC_KEY_OUT(header, key_info,
		     key_info->key_length, black_key + KEY_PRIME_OFFSET);

	/* Set up flags info */
	black_key[FLAGS_OFFSET] = 0;
	if (key_info->flags & FSL_SKO_KEY_SW_KEY) {
		black_key[FLAGS_OFFSET] |= FLAGS_SW_KEY;
	}

	/* Compute and store ICV into Black Key */
	ret = create_icv_calc(user_ctx, &desc_chain, &T_key_info,
			      black_key, original_key_length,
			      black_key + ICV_OFFSET);
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Creation of sah_Key_Link failed due to bad key"
			 " flag!\n");
#endif				/*DIAG_SECURITY_FUNC */
		goto out;
	}

	/* Now get Sahara to do the work. */
#ifdef DIAG_SECURITY_FUNC
	LOG_DIAG("Encrypting key with KEK");
#endif
	SAH_SF_EXECUTE();
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("sah_Descriptor_Chain_Execute() failed");
#endif
		goto out;
	}

	/* Compute T' = SLID_encrypt(T); Result goes to Black Key */
	if (key_info->keystore == NULL) {
		/* Key goes in system keystore */
		ret = do_system_keystore_slot_encrypt(user_ctx,
					T_key_info.userid,  T_key_info.handle,
					T_LENGTH, black_key + T_PRIME_OFFSET);
	} else {
		/* Key goes in user keystore */
		ret = keystore_slot_encrypt(user_ctx,
					    key_info->keystore,
					    T_key_info.userid,
					    T_key_info.handle,
					    T_LENGTH,
				  	    black_key + T_PRIME_OFFSET);
	}

	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("do_scc_slot_encrypt() failed");
#endif
		goto out;
	}

      out:
	key_info->key_length = original_key_length;

	SAH_SF_DESC_CLEAN();
	if (slots_allocated) {
		if (key_info->keystore == NULL) {
			/* Key goes in system keystore */
			(void)do_system_keystore_slot_dealloc(user_ctx,
							      key_info->userid,
							      T_key_info.
							      handle);
			(void)do_system_keystore_slot_dealloc(user_ctx,
							      key_info->userid,
							      KEK_key_info.
							      handle);
		} else {
			/* Key goes in user keystore */
			(void)keystore_slot_dealloc(key_info->keystore,
						    key_info->userid,
				    T_key_info.handle);
			(void)keystore_slot_dealloc(key_info->keystore,
				    key_info->userid,
				    KEK_key_info.handle);
	    }
	}	

	return ret;
}				/* wrap */
/*!
 * Perform unwrapping of a black key into a RED slot
 *
 * @param         user_ctx      A user context from #fsl_shw_register_user().
 * @param[in,out] key_info      The information about the key to be which will
 *                              be unwrapped... key length, slot info, etc.
 * @param         black_key     Encrypted key
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
static fsl_shw_return_t unwrap(fsl_shw_uco_t * user_ctx,
			       fsl_shw_sko_t * key_info,
			       const uint8_t * black_key)
{
	SAH_SF_DCLS;
	uint8_t *hmac = NULL;
	fsl_shw_sko_t t_key_info;
	sah_Link *link1 = NULL;
	sah_Link *link2 = NULL;
	unsigned i;
	unsigned rounded_key_length;
	unsigned original_key_length = key_info->key_length;

	hmac = DESC_TEMP_ALLOC(ICV_LENGTH);

	/* Set up key_info for "T" - use same slot as eventual key */
	fsl_shw_sko_init(&t_key_info, FSL_KEY_ALG_AES);
	t_key_info.userid = key_info->userid;
	t_key_info.handle = key_info->handle;
	t_key_info.flags = key_info->flags;
	t_key_info.key_length = T_LENGTH;
	t_key_info.keystore = key_info->keystore;

	/* Validate SW flags to prevent misuse */
	if ((key_info->flags & FSL_SKO_KEY_SW_KEY)
		&& !(black_key[FLAGS_OFFSET] & FLAGS_SW_KEY)) {
		ret = FSL_RETURN_BAD_FLAG_S;
		goto out;
	}

	/* Compute T = SLID_decrypt(T'); leave in RED slot */
	if (key_info->keystore == NULL) {
		/* Key goes in system keystore */
		ret = do_system_keystore_slot_decrypt(user_ctx,
					key_info->userid,
				    t_key_info.handle,
				    T_LENGTH, 
				    black_key + T_PRIME_OFFSET);
	
	} else {
			/* Key goes in user keystore */
			ret = keystore_slot_decrypt(user_ctx,
							key_info->keystore,
							key_info->userid,
							t_key_info.handle,
							T_LENGTH,
					   	    black_key + T_PRIME_OFFSET);
	}
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Compute ICV = HMAC(T, ownerid | len | alg | key' */
	ret = create_icv_calc(user_ctx, &desc_chain, &t_key_info,
			      black_key, original_key_length, hmac);
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Creation of sah_Key_Link failed due to bad key"
			 " flag!\n");
#endif				/*DIAG_SECURITY_FUNC */
		goto out;
	}
#ifdef DIAG_SECURITY_FUNC
	LOG_DIAG("Validating MAC of wrapped key");
#endif
	SAH_SF_EXECUTE();
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
	SAH_SF_DESC_CLEAN();

	/* Check computed ICV against value in Black Key */
	for (i = 0; i < ICV_LENGTH; i++) {
		if (black_key[ICV_OFFSET + i] != hmac[i]) {
#ifdef DIAG_SECURITY_FUNC
			LOG_DIAG_ARGS("computed ICV fails at offset %i\n", i);

			{
				char buff[300];
				int a;
				for (a = 0; a < ICV_LENGTH; a++)
					sprintf(&(buff[a * 2]), "%02x",
						black_key[ICV_OFFSET + a]);
				buff[a * 2 + 1] = 0;
				LOG_DIAG_ARGS("black key: %s", buff);

				for (a = 0; a < ICV_LENGTH; a++)
					sprintf(&(buff[a * 2]), "%02x",
						hmac[a]);
				buff[a * 2 + 1] = 0;
				LOG_DIAG_ARGS("hmac:      %s", buff);
			}
#endif
			ret = FSL_RETURN_AUTH_FAILED_S;
			goto out;
		}
	}

	/* This is no longer needed. */
	DESC_TEMP_FREE(hmac);

	/* Compute KEK = SHA256(T | ownerid).  Rewrite slot with value */
	header = (SAH_HDR_MDHA_SET_MODE_HASH	/* #8 */
		  ^ sah_insert_mdha_init
		  ^ sah_insert_mdha_algorithm_sha256 ^ sah_insert_mdha_pdata);

	/* Input - Start with T */
	ret = sah_Create_Key_Link(user_ctx->mem_util, &link1, &t_key_info);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Still input - append ownerid */
	ret = sah_Append_Link(user_ctx->mem_util, link1,
			      (void *)&key_info->userid,
			      sizeof(key_info->userid), SAH_USES_LINK_DATA);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Output - KEK goes into RED slot */
	ret = sah_Create_Key_Link(user_ctx->mem_util, &link2, &t_key_info);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Put the Hash calculation into the chain. */
	ret = sah_Append_Desc(user_ctx->mem_util, &desc_chain,
			      header, link1, link2);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Compute KEY = AES-decrypt(KEK, KEY') */
	header = (SAH_HDR_SKHA_SET_MODE_IV_KEY	/* #1 */
		  ^ sah_insert_skha_mode_ctr
		  ^ sah_insert_skha_algorithm_aes
		  ^ sah_insert_skha_modulus_128);
	/* Load KEK in as the key to use */
	DESC_IN_KEY(header, 0, NULL, &t_key_info);

	rounded_key_length = ROUND_LENGTH(original_key_length);
	key_info->key_length = rounded_key_length;

	/* Now set up for computation.  Result in RED */
	header = SAH_HDR_SKHA_ENC_DEC;	/* #4 */
	DESC_IN_KEY(header, rounded_key_length, black_key + KEY_PRIME_OFFSET,
		    key_info);

	/* Perform the operation */
#ifdef DIAG_SECURITY_FUNC
	LOG_DIAG("Decrypting key with KEK");
#endif
	SAH_SF_EXECUTE();

      out:
	key_info->key_length = original_key_length;
	SAH_SF_DESC_CLEAN();

	DESC_TEMP_FREE(hmac);

	/* Erase tracks */
	t_key_info.userid = 0xdeadbeef;
	t_key_info.handle = 0xdeadbeef;

	return ret;
}				/* unwrap */
Пример #8
0
/*!
 * 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;
}