Exemplo n.º 1
0
static int do_create(int argc, char *argv[])
{
	int errorcnt = 0;
	char *e, *s;
	int i, r, len, remove_ext = 0;
	const struct vb2_text_vs_enum *entry;

	while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
		switch (i) {

		case OPT_VERSION:
			opt_version = strtoul(optarg, &e, 0);
			if (!*optarg || (e && *e)) {
				fprintf(stderr,
					"invalid version \"%s\"\n", optarg);
				errorcnt = 1;
			}
			break;

		case OPT_DESC:
			opt_desc = optarg;
			break;

		case OPT_GUID:
			if (VB2_SUCCESS != vb2_str_to_guid(optarg,
							   &opt_guid)) {
				fprintf(stderr, "invalid guid \"%s\"\n",
					optarg);
				errorcnt = 1;
			}
			break;

		case OPT_HASH_ALG:
			/* try string first */
			entry = vb2_lookup_by_name(vb2_text_vs_hash, optarg);
			if (entry) {
				opt_hash_alg = entry->num;
				break;
			}
			/* fine, try number */
			opt_hash_alg = strtoul(optarg, &e, 0);
			if (!*optarg || (e && *e)) {
				fprintf(stderr,
					"invalid hash_alg \"%s\"\n", optarg);
				errorcnt++;
				break;
			}
			if (!vb2_lookup_by_num(vb2_text_vs_hash,
					       opt_hash_alg)) {
				fprintf(stderr,
					"Hash algorithm %d is unsupported\n",
					opt_hash_alg);
				errorcnt++;
			}
			break;

		case '?':
			if (optopt)
				fprintf(stderr, "Unrecognized option: -%c\n",
					optopt);
			else
				fprintf(stderr, "Unrecognized option\n");
			errorcnt++;
			break;
		case ':':
			fprintf(stderr, "Missing argument to -%c\n", optopt);
			errorcnt++;
			break;
		case 0:				/* handled option */
			break;
		default:
			DIE;
		}
	}

	/* If we don't have an input file already, we need one */
	if (!infile) {
		if (argc - optind <= 0) {
			fprintf(stderr, "ERROR: missing input filename\n");
			errorcnt++;
		} else {
			infile = argv[optind++];
		}
	}

	if (errorcnt) {
		print_help(argv[0]);
		return 1;
	}

	/* Decide how to determine the output filenames. */
	if (argc > optind) {
		s = argv[optind++];		/* just use this */
	} else {
		s = infile;			/* based on pem file name */
		remove_ext = 1;
	}

	/* Make an extra-large copy to leave room for filename extensions */
	len = strlen(s) + 20;
	outfile = (char *)malloc(len);
	if (!outfile) {
		fprintf(stderr, "ERROR: malloc() failed\n");
		return 1;
	}
	strcpy(outfile, s);

	if (remove_ext) {
		/* Find the last '/' if any, then the last '.' before that. */
		s = strrchr(outfile, '/');
		if (!s)
			s = outfile;
		s = strrchr(s, '.');
		/* Cut off the extension */
		if (s)
			*s = '\0';
	}
	/* Remember that spot for later */
	outext = outfile + strlen(outfile);

	/* Okay, do it */
	if (vboot_version == VBOOT_VERSION_1_0)
		r = vb1_make_keypair();
	else
		r = vb2_make_keypair();

	free(outfile);
	return r;
}
Exemplo n.º 2
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;
}