Ejemplo n.º 1
0
int vb2_verify_keyblock(struct vb2_keyblock *block,
			uint32_t size,
			const struct vb2_public_key *key,
			const struct vb2_workbuf *wb)
{
	struct vb2_signature *sig = &block->keyblock_signature;
	int rv;

	/* Sanity check keyblock before attempting signature check of data */
	rv = vb2_check_keyblock(block, size, sig);
	if (rv)
		return rv;

	VB2_DEBUG("Checking key block signature...\n");
	rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb);
	if (rv) {
		VB2_DEBUG("Invalid key block signature.\n");
		return VB2_ERROR_KEYBLOCK_SIG_INVALID;
	}

	/* Success */
	return VB2_SUCCESS;
}
Ejemplo n.º 2
0
int vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
			   uint32_t size,
			   const struct vb2_public_key *key,
			   const struct vb2_workbuf *wb)
{
	struct vb2_signature *sig = &preamble->preamble_signature;

	VB2_DEBUG("Verifying preamble.\n");

	/* Sanity checks before attempting signature of data */
	if(size < sizeof(*preamble)) {
		VB2_DEBUG("Not enough data for preamble header\n");
		return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
	}
	if (preamble->header_version_major !=
	    FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
		VB2_DEBUG("Incompatible firmware preamble header version.\n");
		return VB2_ERROR_PREAMBLE_HEADER_VERSION;
	}

	if (preamble->header_version_minor < 1) {
		VB2_DEBUG("Only preamble header 2.1+ supported\n");
		return VB2_ERROR_PREAMBLE_HEADER_OLD;
	}

	if (size < preamble->preamble_size) {
		VB2_DEBUG("Not enough data for preamble.\n");
		return VB2_ERROR_PREAMBLE_SIZE;
	}

	/* Check signature */
	if (vb2_verify_signature_inside(preamble, preamble->preamble_size,
					sig)) {
		VB2_DEBUG("Preamble signature off end of preamble\n");
		return VB2_ERROR_PREAMBLE_SIG_OUTSIDE;
	}

	/* Make sure advertised signature data sizes are sane. */
	if (preamble->preamble_size < sig->data_size) {
		VB2_DEBUG("Signature calculated past end of the block\n");
		return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH;
	}

	if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) {
		VB2_DEBUG("Preamble signature validation failed\n");
		return VB2_ERROR_PREAMBLE_SIG_INVALID;
	}

	/* Verify we signed enough data */
	if (sig->data_size < sizeof(struct vb2_fw_preamble)) {
		VB2_DEBUG("Didn't sign enough data\n");
		return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE;
	}

	/* Verify body signature is inside the signed data */
	if (vb2_verify_signature_inside(preamble, sig->data_size,
					&preamble->body_signature)) {
		VB2_DEBUG("Firmware body signature off end of preamble\n");
		return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE;
	}

	/* Verify kernel subkey is inside the signed data */
	if (vb2_verify_packed_key_inside(preamble, sig->data_size,
					 &preamble->kernel_subkey)) {
		VB2_DEBUG("Kernel subkey off end of preamble\n");
		return VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE;
	}

	/* Success */
	return VB2_SUCCESS;
}
Ejemplo n.º 3
0
int vb2_verify_keyblock(struct vb2_keyblock *block,
			uint32_t size,
			const struct vb2_public_key *key,
			const struct vb2_workbuf *wb)
{
	struct vb2_signature *sig;
	int rv;

	/* Sanity checks before attempting signature of data */
	if(size < sizeof(*block)) {
		VB2_DEBUG("Not enough space for key block header.\n");
		return VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER;
	}
	if (memcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
		VB2_DEBUG("Not a valid verified boot key block.\n");
		return VB2_ERROR_KEYBLOCK_MAGIC;
	}
	if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
		VB2_DEBUG("Incompatible key block header version.\n");
		return VB2_ERROR_KEYBLOCK_HEADER_VERSION;
	}
	if (size < block->keyblock_size) {
		VB2_DEBUG("Not enough data for key block.\n");
		return VB2_ERROR_KEYBLOCK_SIZE;
	}

	/* Check signature */
	sig = &block->keyblock_signature;

	if (vb2_verify_signature_inside(block, block->keyblock_size, sig)) {
		VB2_DEBUG("Key block signature off end of block\n");
		return VB2_ERROR_KEYBLOCK_SIG_OUTSIDE;
	}

	/* Make sure advertised signature data sizes are sane. */
	if (block->keyblock_size < sig->data_size) {
		VB2_DEBUG("Signature calculated past end of block\n");
		return VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH;
	}

	VB2_DEBUG("Checking key block signature...\n");
	rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb);
	if (rv) {
		VB2_DEBUG("Invalid key block signature.\n");
		return VB2_ERROR_KEYBLOCK_SIG_INVALID;
	}

	/* Verify we signed enough data */
	if (sig->data_size < sizeof(struct vb2_keyblock)) {
		VB2_DEBUG("Didn't sign enough data\n");
		return VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE;
	}

	/* Verify data key is inside the block and inside signed data */
	if (vb2_verify_packed_key_inside(block, block->keyblock_size,
					 &block->data_key)) {
		VB2_DEBUG("Data key off end of key block\n");
		return VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE;
	}
	if (vb2_verify_packed_key_inside(block, sig->data_size,
					 &block->data_key)) {
		VB2_DEBUG("Data key off end of signed data\n");
		return VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED;
	}

	/* Success */
	return VB2_SUCCESS;
}
Ejemplo n.º 4
0
static int vb2_sig_from_usbpd1(struct vb2_signature **sig,
			       enum vb2_signature_algorithm sig_alg,
			       enum vb2_hash_algorithm hash_alg,
			       const uint8_t *o_sig,
			       uint32_t o_sig_size,
			       uint32_t data_size)
{
	struct vb2_signature s = {
		.c.magic = VB2_MAGIC_SIGNATURE,
		.c.struct_version_major = VB2_SIGNATURE_VERSION_MAJOR,
		.c.struct_version_minor = VB2_SIGNATURE_VERSION_MINOR,
		.c.fixed_size = sizeof(s),
		.sig_alg = sig_alg,
		.hash_alg = hash_alg,
		.data_size = data_size,
		.sig_size = vb2_rsa_sig_size(sig_alg),
		.sig_offset = sizeof(s),
	};
	uint32_t total_size = sizeof(s) + o_sig_size;
	uint8_t *buf = calloc(1, total_size);
	if (!buf)
		return VB2_ERROR_UNKNOWN;

	memcpy(buf, &s, sizeof(s));
	memcpy(buf + sizeof(s), o_sig, o_sig_size);

	*sig = (struct vb2_signature *)buf;
	return VB2_SUCCESS;
}

static void show_usbpd1_stuff(const char *name,
			      enum vb2_signature_algorithm sig_alg,
			      enum vb2_hash_algorithm hash_alg,
			      const uint8_t *o_pubkey, uint32_t o_pubkey_size)
{
	struct vb2_public_key key;
	struct vb2_packed_key *pkey;
	uint8_t *sha1sum;
	int i;

	vb2_pubkey_from_usbpd1(&key, sig_alg, hash_alg,
			       o_pubkey, o_pubkey_size);

	if (vb2_public_key_pack(&pkey, &key))
		return;

	sha1sum = DigestBuf((uint8_t *)pkey + pkey->key_offset,
			pkey->key_size, SHA1_DIGEST_ALGORITHM);

	printf("USB-PD v1 image:       %s\n", name);
	printf("  Algorithm:           %s %s\n",
	       vb2_lookup_by_num(vb2_text_vs_sig, sig_alg)->name,
	       vb2_lookup_by_num(vb2_text_vs_hash, hash_alg)->name);
	printf("  Key sha1sum:         ");
	for (i = 0; i < SHA1_DIGEST_SIZE; i++)
		printf("%02x", sha1sum[i]);
	printf("\n");

	free(sha1sum);
	free(pkey);
}


/* Returns VB2_SUCCESS or random error code */
static int try_our_own(enum vb2_signature_algorithm sig_alg,
		       enum vb2_hash_algorithm hash_alg,
		       const uint8_t *o_pubkey, uint32_t o_pubkey_size,
		       const uint8_t *o_sig, uint32_t o_sig_size,
		       const uint8_t *data, uint32_t data_size)
{
	struct vb2_public_key pubkey;
	struct vb2_signature *sig;
	uint8_t buf[VB2_WORKBUF_RECOMMENDED_SIZE]
		__attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
	struct vb2_workbuf wb = {
		.buf = buf,
		.size = sizeof(buf),
	};
	int rv = VB2_ERROR_UNKNOWN;

	vb2_pubkey_from_usbpd1(&pubkey, sig_alg, hash_alg,
			       o_pubkey, o_pubkey_size);

	if ((rv = vb2_sig_from_usbpd1(&sig, sig_alg, hash_alg,
				      o_sig, o_sig_size, data_size)))
	    return rv;

	rv = vb2_verify_data(data, data_size, sig, &pubkey, &wb);

	free(sig);

	return rv;
}

/* Returns VB2_SUCCESS if the image validates itself */
static int check_self_consistency(const uint8_t *buf,
				  const char *name,
				  uint32_t ro_size, uint32_t rw_size,
				  uint32_t ro_offset, uint32_t rw_offset,
				  enum vb2_signature_algorithm sig_alg,
				  enum vb2_hash_algorithm hash_alg)
{
	/* Where are the important bits? */
	uint32_t sig_size = vb2_rsa_sig_size(sig_alg);
	uint32_t sig_offset = rw_offset + rw_size - sig_size;
	uint32_t pubkey_size = usbpd1_packed_key_size(sig_alg);
	uint32_t pubkey_offset = ro_offset + ro_size - pubkey_size;
	int rv;

	/* Skip stuff that obviously doesn't work */
	if (sig_size > rw_size || pubkey_size > ro_size)
		return VB2_ERROR_UNKNOWN;

	rv = try_our_own(sig_alg, hash_alg,		   /* algs */
			 buf + pubkey_offset, pubkey_size, /* pubkey blob */
			 buf + sig_offset, sig_size,	   /* sig blob */
			 buf + rw_offset, rw_size - sig_size); /* RW image */

	if (rv == VB2_SUCCESS && name)
		show_usbpd1_stuff(name, sig_alg, hash_alg,
				  buf + pubkey_offset, pubkey_size);

	return rv;
}


int ft_show_usbpd1(const char *name, uint8_t *buf, uint32_t len, void *data)
{
	uint32_t ro_size, rw_size, ro_offset, rw_offset;
	int s, h;

	Debug("%s(): name %s\n", __func__, name);
	Debug("%s(): len  0x%08x (%d)\n", __func__, len, len);

	/* Get image locations */
	if (!parse_size_opts(len, &ro_size, &rw_size, &ro_offset, &rw_offset))
		return 1;

	/* TODO: If we don't have a RO image, ask for a public key
	 * TODO: If we're given an external public key, use it (and its alg) */
	if (!ro_size) {
		printf("Can't find the public key\n");
		return 1;
	}

	/* TODO: Only loop through the numbers we haven't been given */
	for (s = 0; s < ARRAY_SIZE(sigs); s++)
		for (h = 0; h < ARRAY_SIZE(hashes); h++)
			if (!check_self_consistency(buf, name,
						    ro_size, rw_size,
						    ro_offset, rw_offset,
						    sigs[s], hashes[h]))
				return 0;

	printf("This doesn't appear to be a complete usbpd1 image\n");
	return 1;
}