예제 #1
0
static int write_new_preamble(struct bios_area_s *vblock,
			      struct bios_area_s *fw_body,
			      VbPrivateKey *signkey,
			      VbKeyBlockHeader *keyblock)
{
	VbSignature *body_sig;
	VbFirmwarePreambleHeader *preamble;

	body_sig = CalculateSignature(fw_body->buf, fw_body->len, signkey);
	if (!body_sig) {
		fprintf(stderr, "Error calculating body signature\n");
		return 1;
	}

	preamble = CreateFirmwarePreamble(sign_option.version,
					  sign_option.kernel_subkey,
					  body_sig,
					  signkey,
					  sign_option.flags);
	if (!preamble) {
		fprintf(stderr, "Error creating firmware preamble.\n");
		free(body_sig);
		return 1;
	}

	/* Write the new keyblock */
	uint32_t more = keyblock->key_block_size;
	memcpy(vblock->buf, keyblock, more);
	/* and the new preamble */
	memcpy(vblock->buf + more, preamble, preamble->preamble_size);

	free(preamble);
	free(body_sig);

	return 0;
}
예제 #2
0
/* Create a firmware .vblock */
static int Vblock(const char* outfile, const char* keyblock_file,
                  const char* signprivate, uint64_t version,
                  const char* fv_file, const char* kernelkey_file,
                  uint32_t preamble_flags) {

  VbPrivateKey* signing_key;
  VbPublicKey* kernel_subkey;
  VbSignature* body_sig;
  VbFirmwarePreambleHeader* preamble;
  VbKeyBlockHeader* key_block;
  uint64_t key_block_size;
  uint8_t* fv_data;
  uint64_t fv_size;
  FILE* f;
  uint64_t i;

  if (!outfile) {
    VbExError("Must specify output filename\n");
    return 1;
  }
  if (!keyblock_file || !signprivate || !kernelkey_file) {
    VbExError("Must specify all keys\n");
    return 1;
  }
  if (!fv_file) {
    VbExError("Must specify firmware volume\n");
    return 1;
  }

  /* Read the key block and keys */
  key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
  if (!key_block) {
    VbExError("Error reading key block.\n");
    return 1;
  }

  signing_key = PrivateKeyRead(signprivate);
  if (!signing_key) {
    VbExError("Error reading signing key.\n");
    return 1;
  }

  kernel_subkey = PublicKeyRead(kernelkey_file);
  if (!kernel_subkey) {
    VbExError("Error reading kernel subkey.\n");
    return 1;
  }

  /* Read and sign the firmware volume */
  fv_data = ReadFile(fv_file, &fv_size);
  if (!fv_data)
    return 1;
  if (!fv_size) {
    VbExError("Empty firmware volume file\n");
    return 1;
  }
  body_sig = CalculateSignature(fv_data, fv_size, signing_key);
  if (!body_sig) {
    VbExError("Error calculating body signature\n");
    return 1;
  }
  free(fv_data);

  /* Create preamble */
  preamble = CreateFirmwarePreamble(version,
                                    kernel_subkey,
                                    body_sig,
                                    signing_key,
                                    preamble_flags);
  if (!preamble) {
    VbExError("Error creating preamble.\n");
    return 1;
  }

  /* Write the output file */
  f = fopen(outfile, "wb");
  if (!f) {
    VbExError("Can't open output file %s\n", outfile);
    return 1;
  }
  i = ((1 != fwrite(key_block, key_block_size, 1, f)) ||
       (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
  fclose(f);
  if (i) {
    VbExError("Can't write output file %s\n", outfile);
    unlink(outfile);
    return 1;
  }

  /* Success */
  return 0;
}
예제 #3
0
static void test_verify_fw_preamble(const VbPublicKey *public_key,
				    const VbPrivateKey *private_key,
				    const VbPublicKey *kernel_subkey)
{
	struct vb2_fw_preamble *hdr;
	struct vb2_fw_preamble *h;
	struct vb2_public_key rsa;
	uint8_t workbuf[VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES]
		 __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
	struct vb2_workbuf wb;
	uint32_t hsize;

	vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));

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

	TEST_SUCC(vb2_unpack_key(&rsa, (uint8_t *)public_key,
				 public_key->key_offset + public_key->key_size),
		  "vb2_verify_fw_preamble() prereq key");

	hdr = (struct vb2_fw_preamble *)
		CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig,
				       private_key, 0x5678);
	TEST_PTR_NEQ(hdr, NULL,
		     "VerifyFirmwarePreamble() prereq test preamble");
	if (!hdr)
		return;
	hsize = (uint32_t) hdr->preamble_size;
	h = (struct vb2_fw_preamble *)malloc(hsize + 16384);

	Memcpy(h, hdr, hsize);
	TEST_SUCC(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		  "vb2_verify_fw_preamble() ok using key");

	Memcpy(h, hdr, hsize);
	TEST_EQ(vb2_verify_fw_preamble(h, 4, &rsa, &wb),
		VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER,
		"vb2_verify_fw_preamble() size tiny");

	Memcpy(h, hdr, hsize);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize - 1, &rsa, &wb),
		VB2_ERROR_PREAMBLE_SIZE,
		"vb2_verify_fw_preamble() size--");

	/* Buffer is allowed to be bigger than preamble */
	Memcpy(h, hdr, hsize);
	TEST_SUCC(vb2_verify_fw_preamble(h, hsize + 1, &rsa, &wb),
		  "vb2_verify_fw_preamble() size++");

	/* Care about major version but not minor */
	Memcpy(h, hdr, hsize);
	h->header_version_major++;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_HEADER_VERSION
		, "vb2_verify_fw_preamble() major++");

	Memcpy(h, hdr, hsize);
	h->header_version_major--;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_HEADER_VERSION,
		"vb2_verify_fw_preamble() major--");

	Memcpy(h, hdr, hsize);
	h->header_version_minor++;
	resign_fw_preamble(h, private_key);
	TEST_SUCC(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		  "vb2_verify_fw_preamble() minor++");

	Memcpy(h, hdr, hsize);
	h->header_version_minor--;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_HEADER_OLD,
		"vb2_verify_fw_preamble() 2.0 not supported");

	/* Check signature */
	Memcpy(h, hdr, hsize);
	h->preamble_signature.sig_offset = hsize;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_SIG_OUTSIDE,
		"vb2_verify_fw_preamble() sig off end");

	Memcpy(h, hdr, hsize);
	h->preamble_signature.sig_size--;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_SIG_INVALID,
		"vb2_verify_fw_preamble() sig too small");

	Memcpy(h, hdr, hsize);
	((uint8_t *)vb2_packed_key_data(&h->kernel_subkey))[0] ^= 0x34;
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_SIG_INVALID,
		"vb2_verify_fw_preamble() sig mismatch");

	/* Check that we signed header, kernel subkey, and body sig */
	Memcpy(h, hdr, hsize);
	h->preamble_signature.data_size = 4;
	h->kernel_subkey.key_offset = 0;
	h->kernel_subkey.key_size = 0;
	h->body_signature.sig_offset = 0;
	h->body_signature.sig_size = 0;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE,
		"vb2_verify_fw_preamble() didn't sign header");

	Memcpy(h, hdr, hsize);
	h->kernel_subkey.key_offset = hsize;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE,
		"vb2_verify_fw_preamble() kernel subkey off end");

	Memcpy(h, hdr, hsize);
	h->body_signature.sig_offset = hsize;
	resign_fw_preamble(h, private_key);
	TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
		VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE,
		"vb2_verify_fw_preamble() body sig off end");

	/* TODO: verify with extra padding at end of header. */

	free(h);
	free(hdr);
}