skkeysync: Add PK-handing code
Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
This commit is contained in:
parent
74153741c4
commit
03e6a4e2b3
1 changed files with 68 additions and 8 deletions
|
@ -76,11 +76,19 @@ struct key_database_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct key_database_type keydb_types[] = {
|
struct key_database_type keydb_types[] = {
|
||||||
|
{ "PK", EFI_GLOBAL_VARIABLE },
|
||||||
{ "KEK", EFI_GLOBAL_VARIABLE },
|
{ "KEK", EFI_GLOBAL_VARIABLE },
|
||||||
{ "db", EFI_IMAGE_SECURITY_DATABASE_GUID },
|
{ "db", EFI_IMAGE_SECURITY_DATABASE_GUID },
|
||||||
{ "dbx", EFI_IMAGE_SECURITY_DATABASE_GUID },
|
{ "dbx", EFI_IMAGE_SECURITY_DATABASE_GUID },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum keydb_type {
|
||||||
|
KEYDB_PK = 0,
|
||||||
|
KEYDB_KEK = 1,
|
||||||
|
KEYDB_DB = 2,
|
||||||
|
KEYDB_DBX = 3,
|
||||||
|
};
|
||||||
|
|
||||||
static const char *default_keystore_dirs[] = {
|
static const char *default_keystore_dirs[] = {
|
||||||
"/etc/secureboot/keys",
|
"/etc/secureboot/keys",
|
||||||
"/usr/share/secureboot/keys",
|
"/usr/share/secureboot/keys",
|
||||||
|
@ -113,6 +121,7 @@ struct key_database {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct keyset {
|
struct keyset {
|
||||||
|
struct key_database pk;
|
||||||
struct key_database kek;
|
struct key_database kek;
|
||||||
struct key_database db;
|
struct key_database db;
|
||||||
struct key_database dbx;
|
struct key_database dbx;
|
||||||
|
@ -142,6 +151,7 @@ struct sync_context {
|
||||||
struct list_head new_keys;
|
struct list_head new_keys;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
bool dry_run;
|
bool dry_run;
|
||||||
|
bool set_pk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -468,10 +478,12 @@ static int read_filesystem_keydb(struct sync_context *ctx,
|
||||||
|
|
||||||
static int read_keysets(struct sync_context *ctx)
|
static int read_keysets(struct sync_context *ctx)
|
||||||
{
|
{
|
||||||
|
read_firmware_keydb(ctx, &ctx->firmware_keys->pk);
|
||||||
read_firmware_keydb(ctx, &ctx->firmware_keys->kek);
|
read_firmware_keydb(ctx, &ctx->firmware_keys->kek);
|
||||||
read_firmware_keydb(ctx, &ctx->firmware_keys->db);
|
read_firmware_keydb(ctx, &ctx->firmware_keys->db);
|
||||||
read_firmware_keydb(ctx, &ctx->firmware_keys->dbx);
|
read_firmware_keydb(ctx, &ctx->firmware_keys->dbx);
|
||||||
|
|
||||||
|
read_filesystem_keydb(ctx, &ctx->filesystem_keys->pk);
|
||||||
read_filesystem_keydb(ctx, &ctx->filesystem_keys->kek);
|
read_filesystem_keydb(ctx, &ctx->filesystem_keys->kek);
|
||||||
read_filesystem_keydb(ctx, &ctx->filesystem_keys->db);
|
read_filesystem_keydb(ctx, &ctx->filesystem_keys->db);
|
||||||
read_filesystem_keydb(ctx, &ctx->filesystem_keys->dbx);
|
read_filesystem_keydb(ctx, &ctx->filesystem_keys->dbx);
|
||||||
|
@ -479,10 +491,21 @@ static int read_keysets(struct sync_context *ctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_pk(struct sync_context *ctx)
|
||||||
|
{
|
||||||
|
struct key *key;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
list_for_each(&ctx->filesystem_keys->pk.keys, key, list)
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return (i <= 1) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void print_keyset(struct keyset *keyset, const char *name)
|
static void print_keyset(struct keyset *keyset, const char *name)
|
||||||
{
|
{
|
||||||
struct key_database *kdbs[] =
|
struct key_database *kdbs[] =
|
||||||
{ &keyset->kek, &keyset->db, &keyset->dbx };
|
{ &keyset->pk, &keyset->kek, &keyset->db, &keyset->dbx };
|
||||||
struct key *key;
|
struct key *key;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
@ -636,6 +659,7 @@ static int find_new_keys(struct sync_context *ctx)
|
||||||
struct {
|
struct {
|
||||||
struct key_database *fs_kdb, *fw_kdb;
|
struct key_database *fs_kdb, *fw_kdb;
|
||||||
} kdbs[] = {
|
} kdbs[] = {
|
||||||
|
{ &ctx->filesystem_keys->pk, &ctx->firmware_keys->pk },
|
||||||
{ &ctx->filesystem_keys->kek, &ctx->firmware_keys->kek },
|
{ &ctx->filesystem_keys->kek, &ctx->firmware_keys->kek },
|
||||||
{ &ctx->filesystem_keys->db, &ctx->firmware_keys->db },
|
{ &ctx->filesystem_keys->db, &ctx->firmware_keys->db },
|
||||||
{ &ctx->filesystem_keys->dbx, &ctx->firmware_keys->dbx },
|
{ &ctx->filesystem_keys->dbx, &ctx->firmware_keys->dbx },
|
||||||
|
@ -684,7 +708,7 @@ static void print_new_keys(struct sync_context *ctx)
|
||||||
{
|
{
|
||||||
struct fs_keystore_entry *ke;
|
struct fs_keystore_entry *ke;
|
||||||
|
|
||||||
printf("New keys to be added:\n");
|
printf("New keys in filesystem:\n");
|
||||||
|
|
||||||
list_for_each(&ctx->new_keys, ke, new_list)
|
list_for_each(&ctx->new_keys, ke, new_list)
|
||||||
printf(" %s/%s\n", ke->root, ke->name);
|
printf(" %s/%s\n", ke->root, ke->name);
|
||||||
|
@ -753,14 +777,39 @@ out:
|
||||||
|
|
||||||
static int insert_new_keys(struct sync_context *ctx)
|
static int insert_new_keys(struct sync_context *ctx)
|
||||||
{
|
{
|
||||||
struct fs_keystore_entry *ke;
|
struct fs_keystore_entry *ke, *ke_pk;
|
||||||
int rc = 0;
|
int pks, rc;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
|
pks = 0;
|
||||||
|
ke_pk = NULL;
|
||||||
|
|
||||||
list_for_each(&ctx->new_keys, ke, new_list) {
|
list_for_each(&ctx->new_keys, ke, new_list) {
|
||||||
|
|
||||||
|
/* we handle PK last */
|
||||||
|
if (ke->type == &keydb_types[KEYDB_PK]) {
|
||||||
|
ke_pk = ke;
|
||||||
|
pks++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (insert_key(ctx, ke))
|
if (insert_key(ctx, ke))
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
if (pks == 0 || !ctx->set_pk)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (pks > 1) {
|
||||||
|
fprintf(stderr, "Skipping PK update due to mutiple PKs\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = insert_key(ctx, ke_pk);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,14 +819,17 @@ static struct keyset *init_keyset(struct sync_context *ctx)
|
||||||
|
|
||||||
keyset = talloc(ctx, struct keyset);
|
keyset = talloc(ctx, struct keyset);
|
||||||
|
|
||||||
|
list_head_init(&keyset->pk.keys);
|
||||||
|
keyset->pk.type = &keydb_types[KEYDB_PK];
|
||||||
|
|
||||||
list_head_init(&keyset->kek.keys);
|
list_head_init(&keyset->kek.keys);
|
||||||
keyset->kek.type = &keydb_types[0];
|
keyset->kek.type = &keydb_types[KEYDB_KEK];
|
||||||
|
|
||||||
list_head_init(&keyset->db.keys);
|
list_head_init(&keyset->db.keys);
|
||||||
keyset->db.type = &keydb_types[1];
|
keyset->db.type = &keydb_types[KEYDB_DB];
|
||||||
|
|
||||||
list_head_init(&keyset->dbx.keys);
|
list_head_init(&keyset->dbx.keys);
|
||||||
keyset->dbx.type = &keydb_types[2];
|
keyset->dbx.type = &keydb_types[KEYDB_DBX];
|
||||||
|
|
||||||
return keyset;
|
return keyset;
|
||||||
}
|
}
|
||||||
|
@ -788,6 +840,7 @@ static struct option options[] = {
|
||||||
{ "efivars-path", required_argument, NULL, 'e' },
|
{ "efivars-path", required_argument, NULL, 'e' },
|
||||||
{ "verbose", no_argument, NULL, 'v' },
|
{ "verbose", no_argument, NULL, 'v' },
|
||||||
{ "dry-run", no_argument, NULL, 'n' },
|
{ "dry-run", no_argument, NULL, 'n' },
|
||||||
|
{ "pk", no_argument, NULL, 'p' },
|
||||||
{ "no-default-keystores", no_argument, NULL, 'd' },
|
{ "no-default-keystores", no_argument, NULL, 'd' },
|
||||||
{ "keystore", required_argument, NULL, 'k' },
|
{ "keystore", required_argument, NULL, 'k' },
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
|
@ -803,6 +856,7 @@ static void usage(void)
|
||||||
"\t (or regular directory for testing)\n"
|
"\t (or regular directory for testing)\n"
|
||||||
"\t--verbose Print verbose progress information\n"
|
"\t--verbose Print verbose progress information\n"
|
||||||
"\t--dry-run Don't update firmware key databases\n"
|
"\t--dry-run Don't update firmware key databases\n"
|
||||||
|
"\t--pk Set PK\n"
|
||||||
"\t--keystore <dir> Read keys from <dir>/{db,dbx,KEK}/*\n"
|
"\t--keystore <dir> Read keys from <dir>/{db,dbx,KEK}/*\n"
|
||||||
"\t (can be specified multiple times,\n"
|
"\t (can be specified multiple times,\n"
|
||||||
"\t first dir takes precedence)\n"
|
"\t first dir takes precedence)\n"
|
||||||
|
@ -837,7 +891,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int idx, c;
|
int idx, c;
|
||||||
c = getopt_long(argc, argv, "e:dkvhV", options, &idx);
|
c = getopt_long(argc, argv, "e:dpkvhV", options, &idx);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -851,6 +905,9 @@ int main(int argc, char **argv)
|
||||||
case 'k':
|
case 'k':
|
||||||
add_keystore_dir(ctx, optarg);
|
add_keystore_dir(ctx, optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
ctx->set_pk = true;
|
||||||
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
ctx->verbose = true;
|
ctx->verbose = true;
|
||||||
break;
|
break;
|
||||||
|
@ -905,6 +962,9 @@ int main(int argc, char **argv)
|
||||||
print_keyset(ctx->filesystem_keys, "filesystem");
|
print_keyset(ctx->filesystem_keys, "filesystem");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_pk(ctx))
|
||||||
|
fprintf(stderr, "WARNING: multiple PKs found in filesystem\n");
|
||||||
|
|
||||||
find_new_keys(ctx);
|
find_new_keys(ctx);
|
||||||
|
|
||||||
if (ctx->verbose)
|
if (ctx->verbose)
|
||||||
|
|
Loading…
Reference in a new issue