mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-26 01:37:24 +00:00
Enhance 'cgpt find' command to match keyblocks if desired.
This is part of the proposed developer-mode installation process, where we want to detect that whoever is fiddling with the hard drive has already fiddled with it before. Otherwise, we'll make them wait a bit to prevent drive-by updates. BUG=chromium-os:5306 Change-Id: Ifd6dce69180fa818fe14dbc3b1ac3485fb15d1c9 Review URL: http://codereview.chromium.org/3122023
This commit is contained in:
138
cgpt/cmd_find.c
138
cgpt/cmd_find.c
@@ -28,6 +28,10 @@ static void Usage(void)
|
||||
" -v Be verbose in displaying matches (repeatable)\n"
|
||||
" -n Numeric output only\n"
|
||||
" -1 Fail if more than one match is found\n"
|
||||
" -M FILE"
|
||||
" Matching partition data must also contain FILE content\n"
|
||||
" -O NUM"
|
||||
" Byte offset into partition to match content (default 0)\n"
|
||||
"\n", progname);
|
||||
PrintTypes();
|
||||
}
|
||||
@@ -40,6 +44,10 @@ static int set_type = 0;
|
||||
static int set_label = 0;
|
||||
static int oneonly = 0;
|
||||
static int numeric = 0;
|
||||
static uint8_t *matchbuf = NULL;
|
||||
static uint64_t matchlen = 0;
|
||||
static uint64_t matchoffset = 0;
|
||||
static uint8_t *comparebuf = NULL;
|
||||
|
||||
static Guid unique_guid;
|
||||
static Guid type_guid;
|
||||
@@ -47,6 +55,8 @@ static char *label;
|
||||
static int hits = 0;
|
||||
|
||||
#define BUFSIZE 1024
|
||||
// FIXME: currently we only support 512-byte sectors.
|
||||
#define LBA_SIZE 512
|
||||
|
||||
|
||||
// remember one of the possibly many hits
|
||||
@@ -54,6 +64,86 @@ static int match_partnum = 0; // 0 for no match, 1-N for match
|
||||
static char match_filename[BUFSIZE]; // matching filename
|
||||
|
||||
|
||||
// read a file into a buffer, return buffer and update size
|
||||
static uint8_t *ReadFile(const char *filename, uint64_t *size) {
|
||||
FILE *f;
|
||||
uint8_t *buf;
|
||||
|
||||
f = fopen(filename, "rb");
|
||||
if (!f) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
*size = ftell(f);
|
||||
rewind(f);
|
||||
|
||||
buf = malloc(*size);
|
||||
if (!buf) {
|
||||
fclose(f);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(1 != fread(buf, *size, 1, f)) {
|
||||
fclose(f);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// fill comparebuf with the data to be examined, returning true on success.
|
||||
static int FillBuffer(int fd, uint64_t pos, uint64_t count) {
|
||||
uint8_t *bufptr = comparebuf;
|
||||
|
||||
if (-1 == lseek(fd, pos, SEEK_SET))
|
||||
return 0;
|
||||
|
||||
// keep reading until done or error
|
||||
while (count) {
|
||||
ssize_t bytes_read = read(fd, bufptr, count);
|
||||
// negative means error, 0 means (unexpected) EOF
|
||||
if (bytes_read <= 0)
|
||||
return 0;
|
||||
count -= bytes_read;
|
||||
bufptr += bytes_read;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// check partition data content. return true for match, 0 for no match or error
|
||||
static int match_content(struct drive *drive, GptEntry *entry) {
|
||||
uint64_t part_size;
|
||||
|
||||
if (!matchlen)
|
||||
return 1;
|
||||
|
||||
// Ensure that the region we want to match against is inside the partition.
|
||||
part_size = LBA_SIZE * (entry->ending_lba - entry->starting_lba + 1);
|
||||
if (matchoffset + matchlen > part_size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read the partition data.
|
||||
if (!FillBuffer(drive->fd,
|
||||
(LBA_SIZE * entry->starting_lba) + matchoffset,
|
||||
matchlen)) {
|
||||
Error("unable to read partition data\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Compare it
|
||||
if (0 == memcmp(matchbuf, comparebuf, matchlen)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Nope.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// FIXME: This needs to handle /dev/mmcblk0 -> /dev/mmcblk0p3
|
||||
static void showmatch(char *filename, int partnum, GptEntry *entry) {
|
||||
printf("%s%d\n", filename, partnum);
|
||||
@@ -96,7 +186,7 @@ static int do_search(char *filename) {
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (found && match_content(&drive, entry)) {
|
||||
hits++;
|
||||
retval++;
|
||||
showmatch(filename, i+1, entry);
|
||||
@@ -111,7 +201,7 @@ static int do_search(char *filename) {
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define PROC_PARTITIONS "/proc/partitions"
|
||||
#define DEV_DIR "/dev"
|
||||
@@ -128,12 +218,9 @@ static char *is_wholedev(const char *basename) {
|
||||
static char pathname[BUFSIZE]; // we'll return this.
|
||||
char tmpname[BUFSIZE];
|
||||
|
||||
// printf("basename is %s\n", basename);
|
||||
|
||||
// It should be a block device under /dev/,
|
||||
// It should be a block device under /dev/,
|
||||
for (i = 0; devdirs[i]; i++) {
|
||||
sprintf(pathname, "%s/%s", devdirs[i], basename);
|
||||
// printf(" look at %s\n", pathname);
|
||||
|
||||
if (0 != stat(pathname, &statbuf))
|
||||
continue;
|
||||
@@ -143,7 +230,6 @@ static char *is_wholedev(const char *basename) {
|
||||
|
||||
// It should have a symlink called /sys/block/*/device
|
||||
sprintf(tmpname, "%s/%s/device", SYS_BLOCK_DIR, basename);
|
||||
// printf(" look at %s\n", tmpname);
|
||||
|
||||
if (0 != lstat(tmpname, &statbuf))
|
||||
continue;
|
||||
@@ -177,7 +263,7 @@ static int scan_real_devs(void) {
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
int ma, mi;
|
||||
long long unsigned int sz;
|
||||
|
||||
|
||||
if (sscanf(line, " %d %d %llu %128[^\n ]", &ma, &mi, &sz, partname) != 4)
|
||||
continue;
|
||||
|
||||
@@ -187,20 +273,20 @@ static int scan_real_devs(void) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fclose(fp);
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int cmd_find(int argc, char *argv[]) {
|
||||
int i;
|
||||
|
||||
int errorcnt = 0;
|
||||
char *e = 0;
|
||||
int c;
|
||||
|
||||
|
||||
opterr = 0; // quiet, you
|
||||
while ((c=getopt(argc, argv, ":hv1nt:u:l:")) != -1)
|
||||
while ((c=getopt(argc, argv, ":hv1nt:u:l:M:O:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
@@ -232,6 +318,27 @@ int cmd_find(int argc, char *argv[]) {
|
||||
errorcnt++;
|
||||
}
|
||||
break;
|
||||
case 'M':
|
||||
matchbuf = ReadFile(optarg, &matchlen);
|
||||
if (!matchbuf || !matchlen) {
|
||||
Error("Unable to read from %s\n", optarg);
|
||||
errorcnt++;
|
||||
}
|
||||
// Go ahead and allocate space for the comparison too
|
||||
comparebuf = (uint8_t *)malloc(matchlen);
|
||||
if (!comparebuf) {
|
||||
Error("Unable to allocate %" PRIu64 "bytes for comparison buffer\n",
|
||||
matchlen);
|
||||
errorcnt++;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
matchoffset = strtoull(optarg, &e, 0);
|
||||
if (!*optarg || (e && *e)) {
|
||||
Error("invalid argument to -%c: \"%s\"\n", c, optarg);
|
||||
errorcnt++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
Usage();
|
||||
@@ -249,13 +356,16 @@ int cmd_find(int argc, char *argv[]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!set_unique && !set_type && !set_label) {
|
||||
Error("You must specify at least one of -t, -u, or -l\n");
|
||||
errorcnt++;
|
||||
}
|
||||
if (errorcnt)
|
||||
{
|
||||
Usage();
|
||||
return CGPT_FAILED;
|
||||
}
|
||||
|
||||
|
||||
if (optind < argc) {
|
||||
for (i=optind; i<argc; i++)
|
||||
do_search(argv[i]);
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
char* VbootVersion = "VBOOv=018098b3";
|
||||
char* VbootVersion = "VBOOv=b6f38903";
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ function make_pair {
|
||||
# First create the .vbpubk and .vbprivk pair.
|
||||
make_pair "$1" "${2:-4}"
|
||||
|
||||
# Now create a .vblock to hold our .vbpubk. Since it's for developer use, it
|
||||
# Now create a .keyblock to hold our .vbpubk. Since it's for developer use, it
|
||||
# won't be signed, just checksummed. Developer kernels can only be run in
|
||||
# non-recovery mode with the developer switch enabled, but it won't hurt us to
|
||||
# turn on all the flags bits anyway.
|
||||
|
||||
@@ -67,6 +67,10 @@ static int PrintHelp(const char *progname) {
|
||||
"\n"
|
||||
" Required parameters:\n"
|
||||
" --vblock <file> Signature file in .vblock format\n"
|
||||
"\n"
|
||||
" Optional parameters:\n"
|
||||
" --keyblock <file>"
|
||||
" Extract .keyblock to file if verification succeeds\n"
|
||||
"\n",
|
||||
progname);
|
||||
return 1;
|
||||
@@ -165,7 +169,8 @@ static int Sign(const char* filename, const char* keyblock_file,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Verify(const char* filename, const char* vblock_file) {
|
||||
static int Verify(const char* filename, const char* vblock_file,
|
||||
const char* keyblock_file) {
|
||||
uint8_t* file_data;
|
||||
uint64_t file_size;
|
||||
uint8_t* buf;
|
||||
@@ -256,6 +261,14 @@ static int Verify(const char* filename, const char* vblock_file) {
|
||||
}
|
||||
printf("Body verification succeeded.\n");
|
||||
|
||||
if (keyblock_file) {
|
||||
if (0 != WriteFile(keyblock_file, key_block, key_block->key_block_size)) {
|
||||
error("Unable to export keyblock file\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Key block exported to %s\n", keyblock_file);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -329,7 +342,7 @@ int main(int argc, char* argv[]) {
|
||||
fprintf(stderr, "Some required options are missing\n");
|
||||
return PrintHelp(progname);
|
||||
}
|
||||
return Verify(filename, vblock_file);
|
||||
return Verify(filename, vblock_file, keyblock_file);
|
||||
|
||||
default:
|
||||
fprintf(stderr,
|
||||
|
||||
Reference in New Issue
Block a user