sbkeysync: read keystore into kdb->filesystem_keys
Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
This commit is contained in:
parent
5527ef2db4
commit
54e1fbed30
1 changed files with 138 additions and 13 deletions
135
src/sbkeysync.c
135
src/sbkeysync.c
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue