aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kerr <jeremy.kerr@canonical.com>2012-08-24 18:01:37 +0800
committerJeremy Kerr <jeremy.kerr@canonical.com>2012-08-24 20:04:14 +0800
commit03e6a4e2b3897d9635dc63a5abc10a2bb45dd13c (patch)
tree1b6eaee948870e69730e95cafda18df4edf198f8
parent74153741c4d3a6f45ddfa683ff39724ce9fc1a0b (diff)
downloadsbsigntools-03e6a4e2b3897d9635dc63a5abc10a2bb45dd13c.tar.gz
skkeysync: Add PK-handing code
Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
-rw-r--r--src/sbkeysync.c76
1 files changed, 68 insertions, 8 deletions
diff --git a/src/sbkeysync.c b/src/sbkeysync.c
index 3dfb1d8..0fd4c26 100644
--- a/src/sbkeysync.c
+++ b/src/sbkeysync.c
@@ -76,11 +76,19 @@ struct key_database_type {
};
struct key_database_type keydb_types[] = {
+ { "PK", EFI_GLOBAL_VARIABLE },
{ "KEK", EFI_GLOBAL_VARIABLE },
{ "db", 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[] = {
"/etc/secureboot/keys",
"/usr/share/secureboot/keys",
@@ -113,6 +121,7 @@ struct key_database {
};
struct keyset {
+ struct key_database pk;
struct key_database kek;
struct key_database db;
struct key_database dbx;
@@ -142,6 +151,7 @@ struct sync_context {
struct list_head new_keys;
bool verbose;
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)
{
+ read_firmware_keydb(ctx, &ctx->firmware_keys->pk);
read_firmware_keydb(ctx, &ctx->firmware_keys->kek);
read_firmware_keydb(ctx, &ctx->firmware_keys->db);
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->db);
read_filesystem_keydb(ctx, &ctx->filesystem_keys->dbx);
@@ -479,10 +491,21 @@ static int read_keysets(struct sync_context *ctx)
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)
{
struct key_database *kdbs[] =
- { &keyset->kek, &keyset->db, &keyset->dbx };
+ { &keyset->pk, &keyset->kek, &keyset->db, &keyset->dbx };
struct key *key;
unsigned int i;
@@ -636,6 +659,7 @@ static int find_new_keys(struct sync_context *ctx)
struct {
struct key_database *fs_kdb, *fw_kdb;
} kdbs[] = {
+ { &ctx->filesystem_keys->pk, &ctx->firmware_keys->pk },
{ &ctx->filesystem_keys->kek, &ctx->firmware_keys->kek },
{ &ctx->filesystem_keys->db, &ctx->firmware_keys->db },
{ &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;
- printf("New keys to be added:\n");
+ printf("New keys in filesystem:\n");
list_for_each(&ctx->new_keys, ke, new_list)
printf(" %s/%s\n", ke->root, ke->name);
@@ -753,14 +777,39 @@ out:
static int insert_new_keys(struct sync_context *ctx)
{
- struct fs_keystore_entry *ke;
- int rc = 0;
+ struct fs_keystore_entry *ke, *ke_pk;
+ int pks, rc;
+
+ rc = 0;
+ pks = 0;
+ ke_pk = NULL;
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))
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;
}
@@ -770,14 +819,17 @@ static struct keyset *init_keyset(struct sync_context *ctx)
keyset = talloc(ctx, struct keyset);
+ list_head_init(&keyset->pk.keys);
+ keyset->pk.type = &keydb_types[KEYDB_PK];
+
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);
- keyset->db.type = &keydb_types[1];
+ keyset->db.type = &keydb_types[KEYDB_DB];
list_head_init(&keyset->dbx.keys);
- keyset->dbx.type = &keydb_types[2];
+ keyset->dbx.type = &keydb_types[KEYDB_DBX];
return keyset;
}
@@ -788,6 +840,7 @@ static struct option options[] = {
{ "efivars-path", required_argument, NULL, 'e' },
{ "verbose", no_argument, NULL, 'v' },
{ "dry-run", no_argument, NULL, 'n' },
+ { "pk", no_argument, NULL, 'p' },
{ "no-default-keystores", no_argument, NULL, 'd' },
{ "keystore", required_argument, NULL, 'k' },
{ NULL, 0, NULL, 0 },
@@ -803,6 +856,7 @@ static void usage(void)
"\t (or regular directory for testing)\n"
"\t--verbose Print verbose progress information\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 (can be specified multiple times,\n"
"\t first dir takes precedence)\n"
@@ -837,7 +891,7 @@ int main(int argc, char **argv)
for (;;) {
int idx, c;
- c = getopt_long(argc, argv, "e:dkvhV", options, &idx);
+ c = getopt_long(argc, argv, "e:dpkvhV", options, &idx);
if (c == -1)
break;
@@ -851,6 +905,9 @@ int main(int argc, char **argv)
case 'k':
add_keystore_dir(ctx, optarg);
break;
+ case 'p':
+ ctx->set_pk = true;
+ break;
case 'v':
ctx->verbose = true;
break;
@@ -905,6 +962,9 @@ int main(int argc, char **argv)
print_keyset(ctx->filesystem_keys, "filesystem");
}
+ if (check_pk(ctx))
+ fprintf(stderr, "WARNING: multiple PKs found in filesystem\n");
+
find_new_keys(ctx);
if (ctx->verbose)