Exemple #1
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 */
/*!
 * 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 */