fsl_shw_return_t fsl_shw_read_key(fsl_shw_uco_t * user_ctx,
				  fsl_shw_sko_t * key_info, uint8_t * key)
{
	SAH_SF_DCLS;

	SAH_SF_USER_CHECK();

	if (!(key_info->flags & FSL_SKO_KEY_ESTABLISHED)
	    || !(key_info->flags & FSL_SKO_KEY_SW_KEY)) {
		ret = FSL_RETURN_BAD_FLAG_S;
		goto out;
	}

	if (key_info->keystore == NULL) {
		/* Key lives in system keystore */
		ret = do_system_keystore_slot_read(user_ctx,
						   key_info->userid,
						   key_info->handle,
						   key_info->key_length, key);
	} else {
		/* Key lives in user keystore */
		ret = keystore_slot_read(key_info->keystore,
					 key_info->userid,
					 key_info->handle,
					 key_info->key_length, key);
	}

      out:
	SAH_SF_DESC_CLEAN();

	return ret;
}
/*!
 * De-establish a key so that it can no longer be accessed.
 *
 * The key will need to be re-established before it can again be used.
 *
 * This feature is not available for all platforms, nor for all algorithms and
 * modes.
 *
 * @param      user_ctx         A user context from #fsl_shw_register_user().
 * @param      key_info         The information about the key to be deleted.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_release_key(fsl_shw_uco_t * user_ctx,
				     fsl_shw_sko_t * key_info)
{
	SAH_SF_DCLS;

	SAH_SF_USER_CHECK();

	if (key_info->flags & FSL_SKO_KEY_ESTABLISHED) {
		if (key_info->keystore == NULL) {
			/* Key goes in system keystore */
			do_system_keystore_slot_dealloc(user_ctx,
							key_info->userid,
							key_info->handle);
		} else {
			/* Key goes in user keystore */
			keystore_slot_dealloc(key_info->keystore,
						key_info->userid,
					  	key_info->handle);
		}	
		key_info->flags &= ~(FSL_SKO_KEY_ESTABLISHED |
				     FSL_SKO_KEY_PRESENT);
	}

out:
	SAH_SF_DESC_CLEAN();

	return ret;
}
/*!
 * Wrap a key and retrieve the wrapped value.
 *
 * A wrapped key is a key that has been cryptographically obscured.  It is
 * only able to be used with #fsl_shw_establish_key().
 *
 * This function will also release the key (see #fsl_shw_release_key()) so
 * that it must be re-established before reuse.
 *
 * This feature is not available for all platforms, nor for all algorithms and
 * modes.
 *
 * @param      user_ctx         A user context from #fsl_shw_register_user().
 * @param      key_info         The information about the key to be deleted.
 * @param[out] covered_key      The location to store the 48-octet wrapped key.
 *                              (This size is based upon the maximum key size
 *                              of 32 octets).
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_extract_key(fsl_shw_uco_t * user_ctx,
				     fsl_shw_sko_t * key_info,
				     uint8_t * covered_key)
{
	SAH_SF_DCLS;

	SAH_SF_USER_CHECK();

	/* For now, only blocking mode calls are supported */
	if (user_ctx->flags & FSL_UCO_BLOCKING_MODE) {
		if (key_info->flags & FSL_SKO_KEY_ESTABLISHED) {
			ret = wrap(user_ctx, key_info, covered_key);
			if (ret != FSL_RETURN_OK_S) {
				goto out;
			}

			/* Verify that a SW key info really belongs to a SW key */
			if (key_info->flags & FSL_SKO_KEY_SW_KEY) {
			/*  ret = FSL_RETURN_BAD_FLAG_S;
			  goto out;*/
			}

			/* Need to deallocate on successful extraction */
			if (key_info->keystore == NULL) {
				/* Key goes in system keystore */
				ret = do_system_keystore_slot_dealloc(user_ctx,
						key_info->userid, key_info->handle);
			} else {
				/* Key goes in user keystore */
				ret = keystore_slot_dealloc(key_info->keystore,
						key_info->userid, key_info->handle);
			}	
			/* Mark key not available in the flags */
			key_info->flags &=
			    ~(FSL_SKO_KEY_ESTABLISHED | FSL_SKO_KEY_PRESENT);
		}
	}

out:
	SAH_SF_DESC_CLEAN();

	return ret;
}
Example #4
0
/*!
 * @brief Authenticate and decrypt a (CCM) stream.
 *
 * @param user_ctx         The user's context
 * @param auth_ctx         Info on this Auth operation
 * @param cipher_key_info  Key to encrypt payload
 * @param auth_key_info    (unused - same key in CCM)
 * @param auth_data_length Length in bytes of @a auth_data
 * @param auth_data        Any auth-only data
 * @param payload_length   Length in bytes of @a payload
 * @param ct               The encrypted data
 * @param auth_value       The authentication code to validate
 * @param[out] payload     The location to store decrypted data
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_auth_decrypt(fsl_shw_uco_t * user_ctx,
				      fsl_shw_acco_t * auth_ctx,
				      fsl_shw_sko_t * cipher_key_info,
				      fsl_shw_sko_t * auth_key_info,
				      uint32_t auth_data_length,
				      const uint8_t * auth_data,
				      uint32_t payload_length,
				      const uint8_t * ct,
				      const uint8_t * auth_value,
				      uint8_t * payload)
{
	SAH_SF_DCLS;
	uint8_t *calced_auth = NULL;
	unsigned blocking = user_ctx->flags & FSL_UCO_BLOCKING_MODE;

	SAH_SF_USER_CHECK();

	/* Only support INIT and FINALIZE flags right now. */
	if (auth_ctx->mode != FSL_ACC_MODE_CCM) {
		ret = FSL_RETURN_BAD_MODE_S;
		goto out;
	}
	if ((auth_ctx->flags & (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_LOAD |
				FSL_ACCO_CTX_SAVE | FSL_ACCO_CTX_FINALIZE))
	    != (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_FINALIZE)) {
		ret = FSL_RETURN_BAD_FLAG_S;
		goto out;
	}
	ret = load_ctr_key(&desc_chain, user_ctx, auth_ctx, cipher_key_info);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Decrypt the MAC which the user passed in */
	header = SAH_HDR_SKHA_ENC_DEC;
	DESC_IN_OUT(header,
		    auth_ctx->mac_length, auth_value,
		    auth_ctx->mac_length, auth_ctx->unencrypted_mac);

#ifndef NO_ZERO_IV_LOAD
	ret = load_dummy_iv(&desc_chain, user_ctx, 1,
			    auth_ctx->auth_info.CCM_ctx_info.block_size_bytes);
#endif

	if (auth_data_length > 0) {
		ret = add_assoc_preamble(&desc_chain, user_ctx,
					 auth_ctx, auth_data, auth_data_length);
		if (ret != FSL_RETURN_OK_S) {
			goto out;
		}
	}
	/* if auth_data_length > 0 */
	ret = process_payload(&desc_chain, user_ctx, 0,
			      payload_length, ct, payload);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Now pull CBC context (unencrypted MAC) out for comparison. */
	/* Need to allocate a place for it, to handle non-blocking mode
	 * when this stack frame will disappear!
	 */
	calced_auth = DESC_TEMP_ALLOC(auth_ctx->mac_length);
	ret = extract_mac(&desc_chain, user_ctx,
			  auth_ctx->mac_length, calced_auth);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	if (!blocking) {
		/* get_results will need this for comparison */
		desc_chain->out1_ptr = calced_auth;
		desc_chain->out2_ptr = auth_ctx->unencrypted_mac;
		desc_chain->out_len = auth_ctx->mac_length;
	}

	SAH_SF_EXECUTE();

	if (blocking && (ret == FSL_RETURN_OK_S)) {
		unsigned i;
		/* Validate the auth code */
		for (i = 0; i < auth_ctx->mac_length; i++) {
			if (calced_auth[i] != auth_ctx->unencrypted_mac[i]) {
				ret = FSL_RETURN_AUTH_FAILED_S;
				break;
			}
		}
	}

      out:
	SAH_SF_DESC_CLEAN();
	DESC_TEMP_FREE(calced_auth);

	(void)auth_key_info;
	return ret;
}				/* fsl_shw_gen_decrypt() */
Example #5
0
/*!
 * @brief Generate a (CCM) auth code and encrypt the payload.
 *
 * This is a very complicated function.  Seven (or eight) descriptors are
 * required to perform a CCM calculation.
 *
 * First:  Load CTR0 and key.
 *
 * Second: Run an octet of data through to bump to CTR1.  (This could be
 * done in software, but software will have to bump and later decrement -
 * or copy and bump.
 *
 * Third: (in Virtio) Load a descriptor with data of zeros for CBC IV.
 *
 * Fourth: Run any (optional) "additional data" through the CBC-mode
 * portion of the algorithm.
 *
 * Fifth: Run the payload through in CCM mode.
 *
 * Sixth: Extract the unencrypted MAC.
 *
 * Seventh: Load CTR0.
 *
 * Eighth: Encrypt the MAC.
 *
 * @param user_ctx         The user's context
 * @param auth_ctx         Info on this Auth operation
 * @param cipher_key_info  Key to encrypt payload
 * @param auth_key_info    (unused - same key in CCM)
 * @param auth_data_length Length in bytes of @a auth_data
 * @param auth_data        Any auth-only data
 * @param payload_length   Length in bytes of @a payload
 * @param payload          The data to encrypt
 * @param[out] ct          The location to store encrypted data
 * @param[out] auth_value  The location to store authentication code
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_gen_encrypt(fsl_shw_uco_t * user_ctx,
				     fsl_shw_acco_t * auth_ctx,
				     fsl_shw_sko_t * cipher_key_info,
				     fsl_shw_sko_t * auth_key_info,
				     uint32_t auth_data_length,
				     const uint8_t * auth_data,
				     uint32_t payload_length,
				     const uint8_t * payload,
				     uint8_t * ct, uint8_t * auth_value)
{
	SAH_SF_DCLS;

	SAH_SF_USER_CHECK();

	if (auth_ctx->mode != FSL_ACC_MODE_CCM) {
		ret = FSL_RETURN_BAD_MODE_S;
		goto out;
	}

	/* Only support INIT and FINALIZE flags right now. */
	if ((auth_ctx->flags & (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_LOAD |
				FSL_ACCO_CTX_SAVE | FSL_ACCO_CTX_FINALIZE))
	    != (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_FINALIZE)) {
		ret = FSL_RETURN_BAD_FLAG_S;
		goto out;
	}
	ret = load_ctr_key(&desc_chain, user_ctx, auth_ctx, cipher_key_info);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	header = SAH_HDR_SKHA_ENC_DEC;
	DESC_IN_OUT(header, auth_ctx->cipher_ctx_info.block_size_bytes,
		    garbage_output, auth_ctx->cipher_ctx_info.block_size_bytes,
		    garbage_output);

#ifndef NO_ZERO_IV_LOAD
	ret = load_dummy_iv(&desc_chain, user_ctx,
			    1,
			    auth_ctx->auth_info.CCM_ctx_info.block_size_bytes);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}
#endif

	if (auth_data_length > 0) {
		ret = add_assoc_preamble(&desc_chain, user_ctx,
					 auth_ctx, auth_data, auth_data_length);
		if (ret != FSL_RETURN_OK_S) {
			goto out;
		}
	}
	/* if auth_data_length > 0 */
	ret = process_payload(&desc_chain, user_ctx, 1,
			      payload_length, payload, ct);

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

	/* Pull out the CBC-MAC value. */
	ret = extract_mac(&desc_chain, user_ctx,
			  auth_ctx->mac_length, auth_ctx->unencrypted_mac);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Now load CTR0 in, and encrypt the MAC */
	ret = encrypt_mac(&desc_chain, user_ctx, auth_ctx,
			  auth_ctx->unencrypted_mac, auth_value);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	SAH_SF_EXECUTE();

      out:
	SAH_SF_DESC_CLEAN();

	(void)auth_key_info;
	return ret;
}				/* fsl_shw_gen_encrypt() */
Example #6
0
/*!
 * @brief Authenticate and decrypt a (CCM) stream.
 *
 * @param user_ctx         The user's context
 * @param auth_ctx         Info on this Auth operation
 * @param cipher_key_info  Key to encrypt payload
 * @param auth_key_info    (unused - same key in CCM)
 * @param auth_data_length Length in bytes of @a auth_data
 * @param auth_data        Any auth-only data
 * @param payload_length   Length in bytes of @a payload
 * @param ct               The encrypted data
 * @param auth_value       The authentication code to validate
 * @param[out] payload     The location to store decrypted data
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_auth_decrypt(fsl_shw_uco_t * user_ctx,
				      fsl_shw_acco_t * auth_ctx,
				      fsl_shw_sko_t * cipher_key_info,
				      fsl_shw_sko_t * auth_key_info,
				      uint32_t auth_data_length,
				      const uint8_t * auth_data,
				      uint32_t payload_length,
				      const uint8_t * ct,
				      const uint8_t * auth_value,
				      uint8_t * payload)
{
	SAH_SF_DCLS;
#if defined(FSL_HAVE_SAHARA2) || defined(USE_S2_CCM_DECRYPT_CHAIN)
	uint8_t *calced_auth = NULL;
	unsigned blocking = user_ctx->flags & FSL_UCO_BLOCKING_MODE;
#endif

	SAH_SF_USER_CHECK();

	/* Only support CCM */
	if (auth_ctx->mode != FSL_ACC_MODE_CCM) {
		ret = FSL_RETURN_BAD_MODE_S;
		goto out;
	}
	/* Only support INIT and FINALIZE flags right now. */
	if ((auth_ctx->flags & (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_LOAD |
				FSL_ACCO_CTX_SAVE | FSL_ACCO_CTX_FINALIZE))
	    != (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_FINALIZE)) {
		ret = FSL_RETURN_BAD_FLAG_S;
		goto out;
	}

	/* Load CTR0 and Key */
	header = SAH_HDR_SKHA_SET_MODE_IV_KEY
	    ^ sah_insert_skha_mode_ctr ^ sah_insert_skha_modulus_128;
#if defined (FSL_HAVE_SAHARA4) && !defined (USE_S2_CCM_DECRYPT_CHAIN)
	header ^= sah_insert_skha_aux0;
#endif
	DESC_IN_KEY(header,
		    auth_ctx->cipher_ctx_info.block_size_bytes,
		    auth_ctx->cipher_ctx_info.context, cipher_key_info);

	/* Decrypt the MAC which the user passed in */
	header = SAH_HDR_SKHA_ENC_DEC;
	DESC_IN_OUT(header,
		    auth_ctx->mac_length, auth_value,
		    auth_ctx->mac_length, auth_ctx->unencrypted_mac);

#if defined(FSL_HAVE_SAHARA2) || defined(USE_S2_CCM_DECRYPT_CHAIN)
#ifndef NO_ZERO_IV_LOAD
	header = (SAH_HDR_SKHA_SET_MODE_IV_KEY
		  ^ sah_insert_skha_encrypt ^ sah_insert_skha_mode_cbc);
	DESC_IN_IN(header,
		   auth_ctx->auth_info.CCM_ctx_info.block_size_bytes,
		   block_zeros, 0, NULL);
#endif
#endif

	ret = add_assoc_preamble(&desc_chain, user_ctx,
				 auth_ctx, 0, auth_data, auth_data_length);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Process the payload */
	header = (SAH_HDR_SKHA_SET_MODE_ENC_DEC
		  ^ sah_insert_skha_mode_ccm ^ sah_insert_skha_modulus_128);
#if defined (FSL_HAVE_SAHARA4) && !defined (USE_S2_CCM_DECRYPT_CHAIN)
	header ^= sah_insert_skha_aux0;
#endif
	if (payload_length != 0) {
		DESC_IN_OUT(header, payload_length, ct, payload_length,
			    payload);
	} else {
		DESC_IN_OUT(header, 0, NULL, 0, NULL);
	}

#if defined (FSL_HAVE_SAHARA2) || defined (USE_S2_CCM_DECRYPT_CHAIN)
	/* Now pull CBC context (unencrypted MAC) out for comparison. */
	/* Need to allocate a place for it, to handle non-blocking mode
	 * when this stack frame will disappear!
	 */
	calced_auth = DESC_TEMP_ALLOC(auth_ctx->mac_length);
	header = SAH_HDR_SKHA_READ_CONTEXT_IV;
	DESC_OUT_OUT(header, 0, NULL, auth_ctx->mac_length, calced_auth);
	if (!blocking) {
		/* get_results will need this for comparison */
		desc_chain->out1_ptr = calced_auth;
		desc_chain->out2_ptr = auth_ctx->unencrypted_mac;
		desc_chain->out_len = auth_ctx->mac_length;
	}
#endif

	SAH_SF_EXECUTE();

#if defined (FSL_HAVE_SAHARA2) || defined (USE_S2_CCM_DECRYPT_CHAIN)
	if (blocking && (ret == FSL_RETURN_OK_S)) {
		unsigned i;
		/* Validate the auth code */
		for (i = 0; i < auth_ctx->mac_length; i++) {
			if (calced_auth[i] != auth_ctx->unencrypted_mac[i]) {
				ret = FSL_RETURN_AUTH_FAILED_S;
				break;
			}
		}
	}
#endif

      out:
	SAH_SF_DESC_CLEAN();
#if defined (FSL_HAVE_SAHARA2) || defined (USE_S2_CCM_DECRYPT_CHAIN)
	DESC_TEMP_FREE(calced_auth);
#endif

	(void)auth_key_info;
	return ret;
}				/* fsl_shw_gen_decrypt() */
Example #7
0
/*!
 * @brief Generate a (CCM) auth code and encrypt the payload.
 *
 * This is a very complicated function.  Seven (or eight) descriptors are
 * required to perform a CCM calculation.
 *
 * First:  Load CTR0 and key.
 *
 * Second: Run an octet of data through to bump to CTR1.  (This could be
 * done in software, but software will have to bump and later decrement -
 * or copy and bump.
 *
 * Third: (in Virtio) Load a descriptor with data of zeros for CBC IV.
 *
 * Fourth: Run any (optional) "additional data" through the CBC-mode
 * portion of the algorithm.
 *
 * Fifth: Run the payload through in CCM mode.
 *
 * Sixth: Extract the unencrypted MAC.
 *
 * Seventh: Load CTR0.
 *
 * Eighth: Encrypt the MAC.
 *
 * @param user_ctx         The user's context
 * @param auth_ctx         Info on this Auth operation
 * @param cipher_key_info  Key to encrypt payload
 * @param auth_key_info    (unused - same key in CCM)
 * @param auth_data_length Length in bytes of @a auth_data
 * @param auth_data        Any auth-only data
 * @param payload_length   Length in bytes of @a payload
 * @param payload          The data to encrypt
 * @param[out] ct          The location to store encrypted data
 * @param[out] auth_value  The location to store authentication code
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_gen_encrypt(fsl_shw_uco_t * user_ctx,
				     fsl_shw_acco_t * auth_ctx,
				     fsl_shw_sko_t * cipher_key_info,
				     fsl_shw_sko_t * auth_key_info,
				     uint32_t auth_data_length,
				     const uint8_t * auth_data,
				     uint32_t payload_length,
				     const uint8_t * payload,
				     uint8_t * ct, uint8_t * auth_value)
{
	SAH_SF_DCLS;

	SAH_SF_USER_CHECK();

	if (auth_ctx->mode == FSL_ACC_MODE_SSL) {
#if SUPPORT_SSL
		ret = do_ssl_gen(user_ctx, auth_ctx, cipher_key_info,
				 auth_key_info, auth_data_length, auth_data,
				 payload_length, payload, ct, auth_value);
#else
		ret = FSL_RETURN_BAD_MODE_S;
#endif
		goto out;
	}

	if (auth_ctx->mode != FSL_ACC_MODE_CCM) {
		ret = FSL_RETURN_BAD_MODE_S;
		goto out;
	}

	/* Only support INIT and FINALIZE flags right now. */
	if ((auth_ctx->flags & (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_LOAD |
				FSL_ACCO_CTX_SAVE | FSL_ACCO_CTX_FINALIZE))
	    != (FSL_ACCO_CTX_INIT | FSL_ACCO_CTX_FINALIZE)) {
		ret = FSL_RETURN_BAD_FLAG_S;
		goto out;
	}

	/* Load CTR0 and Key */
	header = (SAH_HDR_SKHA_SET_MODE_IV_KEY
		  ^ sah_insert_skha_mode_ctr
		  ^ sah_insert_skha_modulus_128 ^ sah_insert_skha_encrypt);
	DESC_IN_KEY(header,
		    auth_ctx->cipher_ctx_info.block_size_bytes,
		    auth_ctx->cipher_ctx_info.context, cipher_key_info);

	/* Encrypt dummy data to bump to CTR1 */
	header = SAH_HDR_SKHA_ENC_DEC;
	DESC_IN_OUT(header, auth_ctx->mac_length, garbage_output,
		    auth_ctx->mac_length, garbage_output);

#if defined(FSL_HAVE_SAHARA2) || defined(USE_S2_CCM_ENCRYPT_CHAIN)
#ifndef NO_ZERO_IV_LOAD
	header = (SAH_HDR_SKHA_SET_MODE_IV_KEY
		  ^ sah_insert_skha_encrypt ^ sah_insert_skha_mode_cbc);
	DESC_IN_IN(header,
		   auth_ctx->auth_info.CCM_ctx_info.block_size_bytes,
		   block_zeros, 0, NULL);
#endif
#endif

	ret = add_assoc_preamble(&desc_chain, user_ctx,
				 auth_ctx, 1, auth_data, auth_data_length);
	if (ret != FSL_RETURN_OK_S) {
		goto out;
	}

	/* Process the payload */
	header = (SAH_HDR_SKHA_SET_MODE_ENC_DEC
		  ^ sah_insert_skha_mode_ccm
		  ^ sah_insert_skha_modulus_128 ^ sah_insert_skha_encrypt);
#if defined (FSL_HAVE_SAHARA4) && !defined (USE_S2_CCM_ENCRYPT_CHAIN)
	header ^= sah_insert_skha_aux0;
#endif
	if (payload_length != 0) {
		DESC_IN_OUT(header, payload_length, payload, payload_length,
			    ct);
	} else {
		DESC_IN_OUT(header, 0, NULL, 0, NULL);
	}			/* if payload_length */

#if defined (FSL_HAVE_SAHARA4) && !defined (USE_S2_CCM_ENCRYPT_CHAIN)
	/* Pull out the CBC-MAC value. */
	DESC_OUT_OUT(SAH_HDR_SKHA_READ_CONTEXT_IV, 0, NULL,
		     auth_ctx->mac_length, auth_value);
#else
	/* Pull out the unencrypted CBC-MAC value. */
	DESC_OUT_OUT(SAH_HDR_SKHA_READ_CONTEXT_IV,
		     0, NULL, auth_ctx->mac_length, auth_ctx->unencrypted_mac);

	/* Now load CTR0 in, and encrypt the MAC */
	header = SAH_HDR_SKHA_SET_MODE_IV_KEY
	    ^ sah_insert_skha_encrypt
	    ^ sah_insert_skha_mode_ctr ^ sah_insert_skha_modulus_128;
	DESC_IN_IN(header,
		   auth_ctx->cipher_ctx_info.block_size_bytes,
		   auth_ctx->cipher_ctx_info.context, 0, NULL);

	header = SAH_HDR_SKHA_ENC_DEC;	/* Desc. #4 SKHA Enc/Dec */
	DESC_IN_OUT(header,
		    auth_ctx->mac_length, auth_ctx->unencrypted_mac,
		    auth_ctx->mac_length, auth_value);
#endif

	SAH_SF_EXECUTE();

      out:
	SAH_SF_DESC_CLEAN();

	(void)auth_key_info;
	return ret;
}				/* fsl_shw_gen_encrypt() */
/*!
 * Place a key into a protected location for use only by cryptographic
 * algorithms.
 *
 * This only needs to be used to a) unwrap a key, or b) set up a key which
 * could be wrapped with a later call to #fsl_shw_extract_key().  Normal
 * cleartext keys can simply be placed into #fsl_shw_sko_t key objects with
 * #fsl_shw_sko_set_key() and used directly.
 *
 * The maximum key size supported for wrapped/unwrapped keys is 32 octets.
 * (This is the maximum reasonable key length on Sahara - 32 octets for an HMAC
 * key based on SHA-256.)  The key size is determined by the @a key_info.  The
 * expected length of @a key can be determined by
 * #fsl_shw_sko_calculate_wrapped_size()
 *
 * The protected key will not be available for use until this operation
 * successfully completes.
 *
 * This feature is not available for all platforms, nor for all algorithms and
 * modes.
 *
 * @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 established.  In the create case, the key
 *                              length must be set.
 * @param      establish_type   How @a key will be interpreted to establish a
 *                              key for use.
 * @param key                   If @a establish_type is #FSL_KEY_WRAP_UNWRAP,
 *                              this is the location of a wrapped key.  If
 *                              @a establish_type is #FSL_KEY_WRAP_CREATE, this
 *                              parameter can be @a NULL.  If @a establish_type
 *                              is #FSL_KEY_WRAP_ACCEPT, this is the location
 *                              of a plaintext key.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_establish_key(fsl_shw_uco_t * user_ctx,
				       fsl_shw_sko_t * key_info,
				       fsl_shw_key_wrap_t establish_type,
				       const uint8_t * key)
{
	SAH_SF_DCLS;
	unsigned original_key_length = key_info->key_length;
	unsigned rounded_key_length;
	unsigned slot_allocated = 0;
	uint32_t old_flags;

	header = SAH_HDR_RNG_GENERATE;	/* Desc. #18 for rand */

	/* TODO: THIS STILL NEEDS TO BE REFACTORED */

	/* Write operations into SCC memory require word-multiple number of
	 * bytes.  For ACCEPT and CREATE functions, the key length may need
	 * to be rounded up.  Calculate. */
	if (LENGTH_PATCH && (original_key_length & LENGTH_PATCH_MASK) != 0) {
		rounded_key_length = original_key_length + LENGTH_PATCH
		    - (original_key_length & LENGTH_PATCH_MASK);
	} else {
		rounded_key_length = original_key_length;
	}

	SAH_SF_USER_CHECK();
	
	if (key_info->flags & FSL_SKO_KEY_ESTABLISHED) {
#ifdef DIAG_SECURITY_FUNC
			ret = FSL_RETURN_BAD_FLAG_S;
			LOG_DIAG("Key already established\n");
#endif
	}


	if (key_info->keystore == NULL) {
		/* Key goes in system keystore */
		ret = do_system_keystore_slot_alloc(user_ctx,
						    key_info->key_length,
						    key_info->userid,
						    &(key_info->handle));
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG_ARGS
		    ("key length: %i, handle: %i, rounded key length: %i",
		     key_info->key_length, key_info->handle,
		     rounded_key_length);
#endif

	} else {
		/* Key goes in user keystore */
		ret = keystore_slot_alloc(key_info->keystore,
					  key_info->key_length,
					  key_info->userid,
					  &(key_info->handle));
	}
	if (ret != FSL_RETURN_OK_S) {
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Slot allocation failed\n");
#endif
		goto out;
	}
	slot_allocated = 1;

	key_info->flags |= FSL_SKO_KEY_ESTABLISHED;
	switch (establish_type) {
	case FSL_KEY_WRAP_CREATE:
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Creating random key\n");
#endif
		/* Use safe version of key length */
		key_info->key_length = rounded_key_length;
		/* Generate descriptor to put random value into */
		DESC_KEY_OUT(header, key_info, 0, NULL);
		/* Restore actual, desired key length */
		key_info->key_length = original_key_length;

		old_flags = user_ctx->flags;
		/* Now put random value into key */
		SAH_SF_EXECUTE();
		/* Restore user's old flag value */
		user_ctx->flags = old_flags;
#ifdef DIAG_SECURITY_FUNC
		if (ret == FSL_RETURN_OK_S) {
			LOG_DIAG("ret is ok");
		} else {
			LOG_DIAG("ret is not ok");
		}
#endif
		break;

	case FSL_KEY_WRAP_ACCEPT:
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Accepting plaintext key\n");
#endif
		if (key == NULL) {
#ifdef DIAG_SECURITY_FUNC
			LOG_DIAG("ACCEPT:  Red Key is NULL");
#endif
			ret = FSL_RETURN_ERROR_S;
			goto out;
		}
		/* Copy in safe number of bytes of Red key */
		if (key_info->keystore == NULL) {
			/* Key goes in system keystore */
			ret = do_system_keystore_slot_load(user_ctx,
						   key_info->userid,
						   key_info->handle, key,
						   rounded_key_length);
		} else {
			/* Key goes in user keystore */
			ret = keystore_slot_load(key_info->keystore,
								 key_info->userid,
								 key_info->handle, key,
								 key_info->key_length);
		}
		break;

	case FSL_KEY_WRAP_UNWRAP:
#ifdef DIAG_SECURITY_FUNC
		LOG_DIAG("Unwrapping wrapped key\n");
#endif
		/* For now, disallow non-blocking calls. */
		if (!(user_ctx->flags & FSL_UCO_BLOCKING_MODE)) {
			ret = FSL_RETURN_BAD_FLAG_S;
		} else if (key == NULL) {
			ret = FSL_RETURN_ERROR_S;
		} else {
			ret = unwrap(user_ctx, key_info, key);
		}
		break;

	default:
		ret = FSL_RETURN_BAD_FLAG_S;
		break;
	}			/* switch */

      out:
	if (slot_allocated && (ret != FSL_RETURN_OK_S)) {
		fsl_shw_return_t scc_err;
		
		if (key_info->keystore == NULL) {
			/* Key goes in system keystore */
			scc_err = do_system_keystore_slot_dealloc(user_ctx,
						  key_info->userid,
						  key_info->handle);
		} else {
			/* Key goes in user keystore */
			scc_err = keystore_slot_dealloc(key_info->keystore,
						key_info->userid,  key_info->handle);
		}
		
		key_info->flags &= ~FSL_SKO_KEY_ESTABLISHED;
	}

	SAH_SF_DESC_CLEAN();

	return ret;
}				/* fsl_shw_establish_key() */
Example #9
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;
}
Example #10
0
/*!
 * Hash a stream of data with a cryptographic hash algorithm.
 *
 * The flags in the @a hash_ctx control the operation of this function.
 *
 * Hashing functions work on 64 octets of message at a time.  Therefore, when
 * any partial hashing of a long message is performed, the message @a length of
 * each segment must be a multiple of 64.  When ready to
 * #FSL_HASH_FLAGS_FINALIZE the hash, the @a length may be any value.
 *
 * With the #FSL_HASH_FLAGS_INIT and #FSL_HASH_FLAGS_FINALIZE flags on, a
 * one-shot complete hash, including padding, will be performed.  The @a length
 * may be any value.
 *
 * The first octets of a data stream can be hashed by setting the
 * #FSL_HASH_FLAGS_INIT and #FSL_HASH_FLAGS_SAVE flags.  The @a length must be
 * a multiple of 64.
 *
 * The flag #FSL_HASH_FLAGS_LOAD is used to load a context previously saved by
 * #FSL_HASH_FLAGS_SAVE.  The two in combination will allow a (multiple-of-64
 * octets) 'middle sequence' of the data stream to be hashed with the
 * beginning.  The @a length must again be a multiple of 64.
 *
 * Since the flag #FSL_HASH_FLAGS_LOAD is used to load a context previously
 * saved by #FSL_HASH_FLAGS_SAVE, the #FSL_HASH_FLAGS_LOAD and
 * #FSL_HASH_FLAGS_FINALIZE flags, used together, can be used to finish the
 * stream.  The @a length may be any value.
 *
 * If the user program wants to do the padding for the hash, it can leave off
 * the #FSL_HASH_FLAGS_FINALIZE flag.  The @a length must then be a multiple of
 * 64 octets.
 *
 * @param      user_ctx  A user context from #fsl_shw_register_user().
 * @param[in,out] hash_ctx Hashing algorithm and state of the cipher.
 * @param      msg       Pointer to the data to be hashed.
 * @param      length    Length, in octets, of the @a msg.
 * @param[out] result    If not null, pointer to where to store the hash
 *                       digest.
 * @param      result_len Number of octets to store in @a result.
 *
 * @return    A return code of type #fsl_shw_return_t.
 */
fsl_shw_return_t fsl_shw_hash(fsl_shw_uco_t * user_ctx,
			      fsl_shw_hco_t * hash_ctx,
			      const uint8_t * msg,
			      uint32_t length,
			      uint8_t * result, uint32_t result_len)
{
	SAH_SF_DCLS;
	unsigned ctx_flags = (hash_ctx->flags & (FSL_HASH_FLAGS_INIT
						 | FSL_HASH_FLAGS_LOAD
						 | FSL_HASH_FLAGS_SAVE
						 | FSL_HASH_FLAGS_FINALIZE));

	SAH_SF_USER_CHECK();

	/* Reset expectations if user gets overly zealous. */
	if (result_len > hash_ctx->digest_length) {
		result_len = hash_ctx->digest_length;
	}

	/* Validate hash ctx flags.
	 * Need INIT or LOAD but not both.
	 * Need SAVE or digest ptr (both is ok).
	 */
	if (((ctx_flags & (FSL_HASH_FLAGS_INIT | FSL_HASH_FLAGS_LOAD))
	     == (FSL_HASH_FLAGS_INIT | FSL_HASH_FLAGS_LOAD))
	    || ((ctx_flags & (FSL_HASH_FLAGS_INIT | FSL_HASH_FLAGS_LOAD)) == 0)
	    || (!(ctx_flags & FSL_HASH_FLAGS_SAVE) && (result == NULL))) {
		ret = FSL_RETURN_BAD_FLAG_S;
		goto out;
	}

	if (ctx_flags & FSL_HASH_FLAGS_INIT) {
		sah_Oct_Str out_ptr;
		unsigned out_len;

		/* Create desc to perform the initial hashing operation */
		/* Desc. #8 w/INIT and algorithm */
		header = SAH_HDR_MDHA_SET_MODE_HASH
		    ^ sah_insert_mdha_init
		    ^ sah_insert_mdha_algorithm[hash_ctx->algorithm];

		/* If user wants one-shot, set padding operation. */
		if (ctx_flags & FSL_HASH_FLAGS_FINALIZE) {
			header ^= sah_insert_mdha_pdata;
		}

		/* Determine where Digest will go - hash_ctx or result */
		if (ctx_flags & FSL_HASH_FLAGS_SAVE) {
			out_ptr = (sah_Oct_Str) hash_ctx->context;
			out_len = hash_ctx->context_register_length;
		} else {
			out_ptr = result;
			out_len = (result_len > hash_ctx->digest_length)
			    ? hash_ctx->digest_length : result_len;
		}

		DESC_IN_OUT(header, length, (sah_Oct_Str) msg, out_len,
			    out_ptr);
	} else {		/* not doing hash INIT */
		void *out_ptr;
		unsigned out_len;

		/*
		 * Build two descriptors -- one to load in context/set mode, the
		 * other to compute & retrieve hash/context value.
		 *
		 * First up - Desc. #6 to load context.
		 */
		/* Desc. #8 w/algorithm */
		header = SAH_HDR_MDHA_SET_MODE_MD_KEY
		    ^ sah_insert_mdha_algorithm[hash_ctx->algorithm];

		if (ctx_flags & FSL_HASH_FLAGS_FINALIZE) {
			header ^= sah_insert_mdha_pdata;
		}

		/* Message Digest (in) */
		DESC_IN_IN(header,
			   hash_ctx->context_register_length,
			   (sah_Oct_Str) hash_ctx->context, 0, NULL);

		if (ctx_flags & FSL_HASH_FLAGS_SAVE) {
			out_ptr = hash_ctx->context;
			out_len = hash_ctx->context_register_length;
		} else {
			out_ptr = result;
			out_len = result_len;
		}

		/* Second -- run data through and retrieve ctx regs */
		/* Desc. #10 - no mode register with this. */
		header = SAH_HDR_MDHA_HASH;
		DESC_IN_OUT(header, length, (sah_Oct_Str) msg, out_len,
			    out_ptr);
	}			/* else not INIT */

	/* Now that execution is rejoined, we can append another descriptor
	   to extract the digest/context a second time, into the result. */
	if ((ctx_flags & FSL_HASH_FLAGS_SAVE)
	    && (result != NULL) && (result_len != 0)) {

		header = SAH_HDR_MDHA_STORE_DIGEST;

		/* Message Digest (out) */
		DESC_IN_OUT(header, 0, NULL,
			    (result_len > hash_ctx->digest_length)
			    ? hash_ctx->digest_length : result_len, result);
	}

	SAH_SF_EXECUTE();

      out:
	SAH_SF_DESC_CLEAN();

	return ret;
}				/* fsl_shw_hash() */