static void VerifyDataTest(const VbPublicKey *public_key,
                           const VbPrivateKey *private_key)
{
	const uint8_t test_data[] = "This is some test data to sign.";
	const uint64_t test_size = sizeof(test_data);
	VbSignature *sig;
	RSAPublicKey *rsa;

	sig = CalculateSignature(test_data, test_size, private_key);
	TEST_PTR_NEQ(sig, 0, "VerifyData() calculate signature");

	rsa = PublicKeyToRSA(public_key);
	TEST_PTR_NEQ(rsa, 0, "VerifyData() calculate rsa");

	if (!sig || !rsa)
		return;

	TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 0,
		"VerifyData() ok");

	sig->sig_size -= 16;
	TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1,
		"VerifyData() wrong sig size");
	sig->sig_size += 16;

	TEST_EQ(VerifyData(test_data, test_size - 1, sig, rsa), 1,
		"VerifyData() input buffer too small");

	GetSignatureData(sig)[0] ^= 0x5A;
	TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1,
		"VerifyData() wrong sig");

	RSAPublicKeyFree(rsa);
	free(sig);
}
static void VerifyDigestTest(const VbPublicKey *public_key,
                             const VbPrivateKey *private_key)
{
	const uint8_t test_data[] = "This is some other test data to sign.";
	VbSignature *sig;
	RSAPublicKey *rsa;
	uint8_t *digest;

	sig = CalculateSignature(test_data, sizeof(test_data), private_key);
	rsa = PublicKeyToRSA(public_key);
	digest = DigestBuf(test_data, sizeof(test_data),
			   (int)public_key->algorithm);
	TEST_NEQ(sig && rsa && digest, 0, "VerifyData() prerequisites");
	if (!sig || !rsa || !digest)
		return;

	TEST_EQ(VerifyDigest(digest, sig, rsa), 0, "VerifyDigest() ok");

	GetSignatureData(sig)[0] ^= 0x5A;
	TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() wrong sig");

	sig->sig_size = 1;
	TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() sig size");

	RSAPublicKeyFree(rsa);
	free(sig);
	VbExFree(digest);
}
Esempio n. 3
0
/*
 * This handles VBLOCK_A and VBLOCK_B while processing a BIOS image. We don't
 * do any signing here. We just check to see if the existing FMAP area contains
 * a firmware preamble so we can preserve its contents. We do the signing once
 * we've looked over all the components.
 */
static int fmap_sign_fw_preamble(const char *name, uint8_t *buf, uint32_t len,
				 void *data)
{
	VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf;
	struct bios_state_s *state = (struct bios_state_s *)data;

	/*
	 * If we have a valid keyblock and fw_preamble, then we can use them to
	 * determine the size of the firmware body. Otherwise, we'll have to
	 * just sign the whole region.
	 */
	if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
		fprintf(stderr, "Warning: %s keyblock is invalid. "
			"Signing the entire FW FMAP region...\n", name);
		goto whatever;
	}

	RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
	if (!rsa) {
		fprintf(stderr, "Warning: %s public key is invalid. "
			"Signing the entire FW FMAP region...\n", name);
		goto whatever;
	}
	uint32_t more = key_block->key_block_size;
	VbFirmwarePreambleHeader *preamble =
		(VbFirmwarePreambleHeader *)(buf + more);
	uint32_t fw_size = preamble->body_signature.data_size;
	struct bios_area_s *fw_body_area = 0;

	switch (state->c) {
	case BIOS_FMAP_VBLOCK_A:
		fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_A];
		/* Preserve the flags if they're not specified */
		if (!sign_option.flags_specified)
			sign_option.flags = preamble->flags;
		break;
	case BIOS_FMAP_VBLOCK_B:
		fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_B];
		break;
	default:
		DIE;
	}

	if (fw_size > fw_body_area->len) {
		fprintf(stderr,
			"%s says the firmware is larger than we have\n",
			name);
		return 1;
	}

	/* Update the firmware size */
	fw_body_area->len = fw_size;

whatever:
	state->area[state->c].is_valid = 1;

	return 0;
}
static void VerifyPublicKeyToRSA(const VbPublicKey *orig_key)
{
	RSAPublicKey *rsa;
	VbPublicKey *key = PublicKeyAlloc(orig_key->key_size, 0, 0);

	PublicKeyCopy(key, orig_key);
	key->algorithm = kNumAlgorithms;
	TEST_EQ((size_t)PublicKeyToRSA(key), 0,
		"PublicKeyToRSA() invalid algorithm");

	PublicKeyCopy(key, orig_key);
	key->key_size -= 1;
	TEST_EQ((size_t)PublicKeyToRSA(key), 0,
		"PublicKeyToRSA() invalid size");

	rsa = PublicKeyToRSA(orig_key);
	TEST_NEQ((size_t)rsa, 0, "PublicKeyToRSA() ok");
	if (rsa) {
		TEST_EQ((int)rsa->algorithm, (int)key->algorithm,
			"PublicKeyToRSA() algorithm");
		RSAPublicKeyFree(rsa);
	}
}
static int Verify(const char* infile, const char* signpubkey,
                  const char* fv_file, const char* kernelkey_file) {

  VbKeyBlockHeader* key_block;
  VbFirmwarePreambleHeader* preamble;
  VbPublicKey* data_key;
  VbPublicKey* sign_key;
  VbPublicKey* kernel_subkey;
  RSAPublicKey* rsa;
  uint8_t* blob;
  uint64_t blob_size;
  uint8_t* fv_data;
  uint64_t fv_size;
  uint64_t now = 0;
  uint32_t flags;

  if (!infile || !signpubkey || !fv_file) {
    VbExError("Must specify filename, signpubkey, and fv\n");
    return 1;
  }

  /* Read public signing key */
  sign_key = PublicKeyRead(signpubkey);
  if (!sign_key) {
    VbExError("Error reading signpubkey.\n");
    return 1;
  }

  /* Read blob */
  blob = ReadFile(infile, &blob_size);
  if (!blob) {
    VbExError("Error reading input file\n");
    return 1;
  }

  /* Read firmware volume */
  fv_data = ReadFile(fv_file, &fv_size);
  if (!fv_data) {
    VbExError("Error reading firmware volume\n");
    return 1;
  }

  /* Verify key block */
  key_block = (VbKeyBlockHeader*)blob;
  if (0 != KeyBlockVerify(key_block, blob_size, sign_key, 0)) {
    VbExError("Error verifying key block.\n");
    return 1;
  }
  free(sign_key);
  now += key_block->key_block_size;

  printf("Key block:\n");
  data_key = &key_block->data_key;
  printf("  Size:                %" PRIu64 "\n", key_block->key_block_size);
  printf("  Flags:               %" PRIu64 " (ignored)\n",
         key_block->key_block_flags);
  printf("  Data key algorithm:  %" PRIu64 " %s\n", data_key->algorithm,
         (data_key->algorithm < kNumAlgorithms ?
          algo_strings[data_key->algorithm] : "(invalid)"));
  printf("  Data key version:    %" PRIu64 "\n", data_key->key_version);
  printf("  Data key sha1sum:    ");
  PrintPubKeySha1Sum(data_key);
  printf("\n");

  rsa = PublicKeyToRSA(&key_block->data_key);
  if (!rsa) {
    VbExError("Error parsing data key.\n");
    return 1;
  }

  /* Verify preamble */
  preamble = (VbFirmwarePreambleHeader*)(blob + now);
  if (0 != VerifyFirmwarePreamble(preamble, blob_size - now, rsa)) {
    VbExError("Error verifying preamble.\n");
    return 1;
  }
  now += preamble->preamble_size;

  flags = VbGetFirmwarePreambleFlags(preamble);
  printf("Preamble:\n");
  printf("  Size:                  %" PRIu64 "\n", preamble->preamble_size);
  printf("  Header version:        %" PRIu32 ".%" PRIu32"\n",
         preamble->header_version_major, preamble->header_version_minor);
  printf("  Firmware version:      %" PRIu64 "\n", preamble->firmware_version);
  kernel_subkey = &preamble->kernel_subkey;
  printf("  Kernel key algorithm:  %" PRIu64 " %s\n",
         kernel_subkey->algorithm,
         (kernel_subkey->algorithm < kNumAlgorithms ?
          algo_strings[kernel_subkey->algorithm] : "(invalid)"));
  printf("  Kernel key version:    %" PRIu64 "\n",
         kernel_subkey->key_version);
  printf("  Kernel key sha1sum:    ");
  PrintPubKeySha1Sum(kernel_subkey);
  printf("\n");
  printf("  Firmware body size:    %" PRIu64 "\n",
         preamble->body_signature.data_size);
  printf("  Preamble flags:        %" PRIu32 "\n", flags);

  /* TODO: verify body size same as signature size */

  /* Verify body */
  if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
    printf("Preamble requests USE_RO_NORMAL; skipping body verification.\n");
  } else {
    if (0 != VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) {
      VbExError("Error verifying firmware body.\n");
      return 1;
    }
    printf("Body verification succeeded.\n");
  }

  if (kernelkey_file) {
    if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) {
      fprintf(stderr,
              "vbutil_firmware: unable to write kernel subkey\n");
      return 1;
    }
  }

  return 0;
}
static void VerifyKernelPreambleTest(const VbPublicKey *public_key,
                                     const VbPrivateKey *private_key)
{
	VbKernelPreambleHeader *hdr;
	VbKernelPreambleHeader *h;
	RSAPublicKey *rsa;
	unsigned hsize;

	/* Create a dummy signature */
	VbSignature *body_sig = SignatureAlloc(56, 78);

	rsa = PublicKeyToRSA(public_key);
	hdr = CreateKernelPreamble(0x1234, 0x100000, 0x300000, 0x4000, body_sig,
				   0, 0, 0, 0, private_key);
	TEST_NEQ(hdr && rsa, 0, "VerifyKernelPreamble() prerequisites");
	if (!hdr)
		return;
	hsize = (unsigned) hdr->preamble_size;
	h = (VbKernelPreambleHeader *)malloc(hsize + 16384);

	TEST_EQ(VerifyKernelPreamble(hdr, hsize, rsa), 0,
		"VerifyKernelPreamble() ok using key");
	TEST_NEQ(VerifyKernelPreamble(hdr, hsize - 1, rsa), 0,
		 "VerifyKernelPreamble() size--");
	TEST_NEQ(VerifyKernelPreamble(hdr, 4, rsa), 0,
		 "VerifyKernelPreamble() size tiny");
	TEST_EQ(VerifyKernelPreamble(hdr, hsize + 1, rsa), 0,
		"VerifyKernelPreamble() size++");

	/* Care about major version but not minor */
	Memcpy(h, hdr, hsize);
	h->header_version_major++;
	ReSignKernelPreamble(h, private_key);
	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		 "VerifyKernelPreamble() major++");

	Memcpy(h, hdr, hsize);
	h->header_version_major--;
	ReSignKernelPreamble(h, private_key);
	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		 "VerifyKernelPreamble() major--");

	Memcpy(h, hdr, hsize);
	h->header_version_minor++;
	ReSignKernelPreamble(h, private_key);
	TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		"VerifyKernelPreamble() minor++");

	Memcpy(h, hdr, hsize);
	h->header_version_minor--;
	ReSignKernelPreamble(h, private_key);
	TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		"VerifyKernelPreamble() minor--");

	/* Check signature */
	Memcpy(h, hdr, hsize);
	h->preamble_signature.sig_offset = hsize;
	ReSignKernelPreamble(h, private_key);
	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		 "VerifyKernelPreamble() sig off end");

	Memcpy(h, hdr, hsize);
	h->preamble_signature.sig_size--;
	ReSignKernelPreamble(h, private_key);
	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		 "VerifyKernelPreamble() sig too small");

	Memcpy(h, hdr, hsize);
	GetSignatureData(&h->body_signature)[0] ^= 0x34;
	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		 "VerifyKernelPreamble() sig mismatch");

	/* Check that we signed header and body sig */
	Memcpy(h, hdr, hsize);
	h->preamble_signature.data_size = 4;
	h->body_signature.sig_offset = 0;
	h->body_signature.sig_size = 0;
	ReSignKernelPreamble(h, private_key);
	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		 "VerifyKernelPreamble() didn't sign header");

	Memcpy(h, hdr, hsize);
	h->body_signature.sig_offset = hsize;
	ReSignKernelPreamble(h, private_key);
	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
		 "VerifyKernelPreamble() body sig off end");

	/* TODO: verify parser can support a bigger header. */

	free(h);
	RSAPublicKeyFree(rsa);
	free(hdr);
}
Esempio n. 7
0
int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
                   const VbPublicKey *key, int hash_only)
{
	const VbSignature *sig;

	/* Sanity checks before attempting signature of data */
	if(size < sizeof(VbKeyBlockHeader)) {
		VBDEBUG(("Not enough space for key block header.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (SafeMemcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
		VBDEBUG(("Not a valid verified boot key block.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
		VBDEBUG(("Incompatible key block header version.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (size < block->key_block_size) {
		VBDEBUG(("Not enough data for key block.\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (!hash_only && !key) {
		VBDEBUG(("Missing required public key.\n"));
		return VBOOT_PUBLIC_KEY_INVALID;
	}

	/*
	 * Check signature or hash, depending on the hash_only parameter. Note
	 * that we don't require a key even if the keyblock has a signature,
	 * because the caller may not care if the keyblock itself is signed
	 * (for example, booting a Google-signed kernel in developer mode).
	 */
	if (hash_only) {
		/* Check hash */
		uint8_t *header_checksum = NULL;
		int rv;

		sig = &block->key_block_checksum;

		if (VerifySignatureInside(block, block->key_block_size, sig)) {
			VBDEBUG(("Key block hash off end of block\n"));
			return VBOOT_KEY_BLOCK_INVALID;
		}
		if (sig->sig_size != SHA512_DIGEST_SIZE) {
			VBDEBUG(("Wrong hash size for key block.\n"));
			return VBOOT_KEY_BLOCK_INVALID;
		}

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

		VBDEBUG(("Checking key block hash only...\n"));
		header_checksum = DigestBuf((const uint8_t *)block,
					    sig->data_size,
					    SHA512_DIGEST_ALGORITHM);
		rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig),
				SHA512_DIGEST_SIZE);
		VbExFree(header_checksum);
		if (rv) {
			VBDEBUG(("Invalid key block hash.\n"));
			return VBOOT_KEY_BLOCK_HASH;
		}
	} else {
		/* Check signature */
		RSAPublicKey *rsa;
		int rv;

		sig = &block->key_block_signature;

		if (VerifySignatureInside(block, block->key_block_size, sig)) {
			VBDEBUG(("Key block signature off end of block\n"));
			return VBOOT_KEY_BLOCK_INVALID;
		}

		rsa = PublicKeyToRSA(key);
		if (!rsa) {
			VBDEBUG(("Invalid public key\n"));
			return VBOOT_PUBLIC_KEY_INVALID;
		}

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

		VBDEBUG(("Checking key block signature...\n"));
		rv = VerifyData((const uint8_t *)block, size, sig, rsa);
		RSAPublicKeyFree(rsa);
		if (rv) {
			VBDEBUG(("Invalid key block signature.\n"));
			return VBOOT_KEY_BLOCK_SIGNATURE;
		}
	}

	/* Verify we signed enough data */
	if (sig->data_size < sizeof(VbKeyBlockHeader)) {
		VBDEBUG(("Didn't sign enough data\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}

	/* Verify data key is inside the block and inside signed data */
	if (VerifyPublicKeyInside(block, block->key_block_size,
				  &block->data_key)) {
		VBDEBUG(("Data key off end of key block\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}
	if (VerifyPublicKeyInside(block, sig->data_size, &block->data_key)) {
		VBDEBUG(("Data key off end of signed data\n"));
		return VBOOT_KEY_BLOCK_INVALID;
	}

	/* Success */
	return VBOOT_SUCCESS;
}
Esempio n. 8
0
VbError_t VbVerifyMemoryBootImage(VbCommonParams *cparams,
                                  VbSelectAndLoadKernelParams *kparams,
                                  void *boot_image,
                                  size_t image_size)
{
    VbError_t retval;
    VbPublicKey* kernel_subkey = NULL;
    uint8_t *kbuf;
    VbKeyBlockHeader *key_block;
    VbSharedDataHeader *shared =
        (VbSharedDataHeader *)cparams->shared_data_blob;
    RSAPublicKey *data_key = NULL;
    VbKernelPreambleHeader *preamble;
    uint64_t body_offset;
    int hash_only = 0;
    int dev_switch;

    if ((boot_image == NULL) || (image_size == 0))
        return VBERROR_INVALID_PARAMETER;

    /* Clear output params in case we fail. */
    kparams->disk_handle = NULL;
    kparams->partition_number = 0;
    kparams->bootloader_address = 0;
    kparams->bootloader_size = 0;
    kparams->flags = 0;
    Memset(kparams->partition_guid, 0, sizeof(kparams->partition_guid));

    kbuf = boot_image;

    /* Read GBB Header */
    cparams->bmp = NULL;
    cparams->gbb = VbExMalloc(sizeof(*cparams->gbb));
    retval = VbGbbReadHeader_static(cparams, cparams->gbb);
    if (VBERROR_SUCCESS != retval) {
        VBDEBUG(("Gbb read header failed.\n"));
        return retval;
    }

    /*
     * We don't care verifying the image if:
     * 1. dev-mode switch is on and
     * 2. GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP is set.
     *
     * Check only the integrity of the image.
     */
    dev_switch = shared->flags & VBSD_BOOT_DEV_SWITCH_ON;
    if (dev_switch && (cparams->gbb->flags &
                       GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP)) {
        VBDEBUG(("Only performing integrity-check.\n"));
        hash_only = 1;
    } else {
        /* Get recovery key. */
        retval = VbGbbReadRecoveryKey(cparams, &kernel_subkey);
        if (VBERROR_SUCCESS != retval) {
            VBDEBUG(("Gbb Read Recovery key failed.\n"));
            return retval;
        }
    }

    /* If we fail at any step, retval returned would be invalid kernel. */
    retval = VBERROR_INVALID_KERNEL_FOUND;

    /* Verify the key block. */
    key_block = (VbKeyBlockHeader *)kbuf;
    if (0 != KeyBlockVerify(key_block, image_size, kernel_subkey,
                            hash_only)) {
        VBDEBUG(("Verifying key block signature/hash failed.\n"));
        goto fail;
    }

    /* Check the key block flags against the current boot mode. */
    if (!(key_block->key_block_flags &
            (dev_switch ? KEY_BLOCK_FLAG_DEVELOPER_1 :
             KEY_BLOCK_FLAG_DEVELOPER_0))) {
        VBDEBUG(("Key block developer flag mismatch.\n"));
        if (hash_only == 0)
            goto fail;
    }

    if (!(key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)) {
        VBDEBUG(("Key block recovery flag mismatch.\n"));
        if (hash_only == 0)
            goto fail;
    }

    /* Get key for preamble/data verification from the key block. */
    data_key = PublicKeyToRSA(&key_block->data_key);
    if (!data_key) {
        VBDEBUG(("Data key bad.\n"));
        goto fail;
    }

    /* Verify the preamble, which follows the key block */
    preamble = (VbKernelPreambleHeader *)(kbuf + key_block->key_block_size);
    if ((0 != VerifyKernelPreamble(preamble,
                                   image_size -
                                   key_block->key_block_size,
                                   data_key))) {
        VBDEBUG(("Preamble verification failed.\n"));
        goto fail;
    }

    VBDEBUG(("Kernel preamble is good.\n"));

    /* Verify kernel data */
    body_offset = key_block->key_block_size + preamble->preamble_size;
    if (0 != VerifyData((const uint8_t *)(kbuf + body_offset),
                        image_size - body_offset,
                        &preamble->body_signature, data_key)) {
        VBDEBUG(("Kernel data verification failed.\n"));
        goto fail;
    }

    VBDEBUG(("Kernel is good.\n"));

    /* Fill in output parameters. */
    kparams->kernel_buffer = kbuf + body_offset;
    kparams->kernel_buffer_size = image_size - body_offset;
    kparams->bootloader_address = preamble->bootloader_address;
    kparams->bootloader_size = preamble->bootloader_size;
    if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS)
        kparams->flags = preamble->flags;

    retval = VBERROR_SUCCESS;

fail:
    VbApiKernelFree(cparams);
    if (NULL != data_key)
        RSAPublicKeyFree(data_key);
    if (NULL != kernel_subkey)
        VbExFree(kernel_subkey);
    return retval;
}