sbkeysync: read keystore into kdb->filesystem_keys

Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
This commit is contained in:
Jeremy Kerr 2012-08-21 18:26:33 +08:00
parent 5527ef2db4
commit 54e1fbed30

View file

@ -89,10 +89,10 @@ struct key {
int id_len;
uint8_t *id;
size_t len;
uint8_t *data;
struct list_node list;
/* set for keys loaded from a filesystem keystore */
struct fs_keystore_entry *keystore_entry;
};
struct key_database {
@ -102,6 +102,7 @@ struct key_database {
};
struct fs_keystore_entry {
const struct key_database_type *type;
const char *root;
const char *name;
uint8_t *data;
@ -318,7 +319,129 @@ static int read_firmware_key_database(struct key_database *kdb,
return 0;
}
static int read_firmware_key_databases(struct sync_context *ctx)
struct keystore_add_ctx {
struct fs_keystore *keystore;
struct fs_keystore_entry *ke;
struct key_database *kdb;
};
static int keystore_add_key(EFI_SIGNATURE_DATA *sigdata, int len,
const EFI_GUID *type, void *arg)
{
struct keystore_add_ctx *add_ctx = arg;
struct key *key;
int rc;
key = talloc(add_ctx->kdb, struct key);
key->keystore_entry = add_ctx->ke;
key->type = *type;
rc = key_id(key, type, sigdata->SignatureData, len,
&key->id, &key->id_len);
if (rc) {
talloc_free(key);
return 0;
}
/* add a reference to the data: we don't want it to be
* deallocated if the keystore is deallocated before the
* struct key. */
talloc_reference(key, add_ctx->ke->data);
list_add(&add_ctx->kdb->filesystem_keys, &key->list);
return 0;
}
static void __attribute__((format(printf, 2, 3))) print_keystore_key_error(
struct fs_keystore_entry *ke, const char *fmt, ...)
{
char *errstr;
va_list ap;
va_start(ap, fmt);
errstr = talloc_vasprintf(ke, fmt, ap);
fprintf(stderr, "Invalid key %s/%s\n - %s\n", ke->root, ke->name,
errstr);
talloc_free(errstr);
va_end(ap);
}
static int read_keystore_key_database(struct key_database *kdb,
struct fs_keystore *keystore)
{
EFI_GUID cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
EFI_VARIABLE_AUTHENTICATION_2 *auth;
struct keystore_add_ctx add_ctx;
struct fs_keystore_entry *ke;
int rc;
add_ctx.keystore = keystore;
add_ctx.kdb = kdb;
list_for_each(&keystore->keys, ke, list) {
unsigned int len;
void *buf;
if (ke->len == 0)
continue;
if (ke->type != kdb->type)
continue;
/* parse the three data structures:
* EFI_VARIABLE_AUTHENTICATION_2 token
* EFI_SIGNATURE_LIST
* EFI_SIGNATURE_DATA
* ensuring that we have enough data for each
*/
buf = ke->data;
len = ke->len;
if (len < sizeof(*auth)) {
print_keystore_key_error(ke, "does not contain an "
"EFI_VARIABLE_AUTHENTICATION_2 descriptor");
continue;
}
auth = buf;
if (guidcmp(&auth->AuthInfo.CertType, &cert_type_pkcs7)) {
print_keystore_key_error(ke, "unknown cert type");
continue;
}
if (auth->AuthInfo.Hdr.dwLength > len) {
print_keystore_key_error(ke,
"invalid WIN_CERTIFICATE length");
continue;
}
/* the dwLength field includes the size of the WIN_CERTIFICATE,
* but not the other data in the EFI_VARIABLE_AUTHENTICATION_2
* descriptor */
buf += sizeof(*auth) - sizeof(auth->AuthInfo) +
auth->AuthInfo.Hdr.dwLength;
len -= sizeof(*auth) - sizeof(auth->AuthInfo) +
auth->AuthInfo.Hdr.dwLength;
add_ctx.ke = ke;
rc = sigdb_iterate(buf, len, keystore_add_key, &add_ctx);
if (rc) {
print_keystore_key_error(ke, "error parsing "
"EFI_SIGNATURE_LIST");
continue;
}
}
return 0;
}
static int read_key_databases(struct sync_context *ctx)
{
struct key_database *kdbs[] = {
ctx->kek,
@ -330,6 +453,7 @@ static int read_firmware_key_databases(struct sync_context *ctx)
for (i = 0; i < ARRAY_SIZE(kdbs); i++) {
struct key_database *kdb = kdbs[i];
read_firmware_key_database(kdb, ctx->efivars_dir);
read_keystore_key_database(kdb, ctx->fs_keystore);
}
return 0;
@ -441,6 +565,7 @@ static int update_keystore(struct fs_keystore *keystore, const char *root)
ke = talloc(keystore, struct fs_keystore_entry);
ke->name = filename;
ke->root = root;
ke->type = &keydb_types[i];
talloc_steal(ke, ke->name);
if (keystore_entry_read(ke))
@ -604,8 +729,8 @@ int main(int argc, char **argv)
}
read_firmware_key_databases(ctx);
read_keystore(ctx);
read_key_databases(ctx);
if (ctx->verbose) {
print_key_databases(ctx);