Exemplo n.º 1
0
/**
 * Do next chunk of hashing work, if any.
 */
static void vboot_hash_next_chunk(void)
{
	int size;

	/* Handle abort */
	if (want_abort) {
		in_progress = 0;
		vboot_hash_abort();
		return;
	}

	/* Compute the next chunk of hash */
	size = MIN(CHUNK_SIZE, data_size - curr_pos);
	SHA256_update(&ctx, (const uint8_t *)(CONFIG_FLASH_BASE +
					      data_offset + curr_pos), size);

	curr_pos += size;
	if (curr_pos >= data_size) {
		/* Store the final hash */
		hash = SHA256_final(&ctx);
		CPRINTS("hash done %.*h", SHA256_DIGEST_SIZE, hash);

		in_progress = 0;

		/* Handle receiving abort during finalize */
		if (want_abort)
			vboot_hash_abort();

		return;
	}

	/* If we're still here, more work to do; come back later */
	hook_call_deferred(vboot_hash_next_chunk, WORK_INTERVAL_US);
}
static int read_and_hash_chunk(int offset, int size)
{
	char *buf;
	int rv;

	if (size == 0)
		return EC_SUCCESS;

	rv = shared_mem_acquire(size, &buf);
	if (rv == EC_ERROR_BUSY) {
		/* Couldn't update hash right now; try again later */
		hook_call_deferred(vboot_hash_next_chunk, WORK_INTERVAL_US);
		return rv;
	} else if (rv != EC_SUCCESS) {
		vboot_hash_abort();
		return rv;
	}

	rv = flash_read(offset, size, buf);
	if (rv == EC_SUCCESS)
		SHA256_update(&ctx, (const uint8_t *)buf, size);
	else
		vboot_hash_abort();

	shared_mem_release(buf);
	return rv;
}
Exemplo n.º 3
0
static int host_command_vboot_hash(struct host_cmd_handler_args *args)
{
	const struct ec_params_vboot_hash *p = args->params;
	struct ec_response_vboot_hash *r = args->response;
	int rv;

	switch (p->cmd) {
	case EC_VBOOT_HASH_GET:
		fill_response(r);
		args->response_size = sizeof(*r);
		return EC_RES_SUCCESS;

	case EC_VBOOT_HASH_ABORT:
		vboot_hash_abort();
		return EC_RES_SUCCESS;

	case EC_VBOOT_HASH_START:
	case EC_VBOOT_HASH_RECALC:
		rv = host_start_hash(p);
		if (rv != EC_RES_SUCCESS)
			return rv;

		/* Wait for hash to finish if command is RECALC */
		if (p->cmd == EC_VBOOT_HASH_RECALC)
			while (in_progress)
				usleep(1000);

		fill_response(r);
		args->response_size = sizeof(*r);
		return EC_RES_SUCCESS;

	default:
		return EC_RES_INVALID_PARAM;
	}
}
Exemplo n.º 4
0
static int command_hash(int argc, char **argv)
{
	uint32_t offset = CONFIG_FW_RW_OFF;
	uint32_t size = CONFIG_FW_RW_SIZE;
	char *e;

	if (argc == 1) {
		ccprintf("Offset: 0x%08x\n", data_offset);
		ccprintf("Size:   0x%08x (%d)\n", data_size, data_size);
		ccprintf("Digest: ");
		if (want_abort)
			ccprintf("(aborting)\n");
		else if (in_progress)
			ccprintf("(in progress)\n");
		else if (hash)
			ccprintf("%.*h\n", SHA256_DIGEST_SIZE, hash);
		else
			ccprintf("(invalid)\n");

		return EC_SUCCESS;
	}

	if (argc == 2) {
		if (!strcasecmp(argv[1], "abort")) {
			vboot_hash_abort();
			return EC_SUCCESS;
		} else if (!strcasecmp(argv[1], "rw")) {
			return vboot_hash_start(
				CONFIG_FW_RW_OFF,
				system_get_image_used(SYSTEM_IMAGE_RW),
				NULL, 0);
		} else if (!strcasecmp(argv[1], "ro")) {
			return vboot_hash_start(
				CONFIG_FW_RO_OFF,
				system_get_image_used(SYSTEM_IMAGE_RO),
				NULL, 0);
		}
	}

	if (argc >= 3) {
		offset = strtoi(argv[1], &e, 0);
		if (*e)
			return EC_ERROR_PARAM1;

		size = strtoi(argv[2], &e, 0);
		if (*e)
			return EC_ERROR_PARAM2;
	}

	if (argc == 4) {
		int nonce = strtoi(argv[3], &e, 0);
		if (*e)
			return EC_ERROR_PARAM3;

		return vboot_hash_start(offset, size,
					(const uint8_t *)&nonce,
					sizeof(nonce));
	} else
		return vboot_hash_start(offset, size, NULL, 0);
}
Exemplo n.º 5
0
int vboot_hash_invalidate(int offset, int size)
{
	/* Don't invalidate if passed an invalid region */
	if (offset < 0 || size <= 0 || offset + size < 0)
		return 0;

	/* Don't invalidate if hash is already invalid */
	if (!hash)
		return 0;

	/* No overlap if passed region is off either end of hashed region */
	if (offset + size <= data_offset || offset >= data_offset + data_size)
		return 0;

	/* Invalidate the hash */
	CPRINTS("hash invalidated 0x%08x 0x%08x", offset, size);
	vboot_hash_abort();
	return 1;
}