1
0
mirror of https://git.code.sf.net/p/linux-ima/ima-evm-utils synced 2025-04-27 22:32:31 +02:00

ima-evm-utils: support verifying the measurement list using multiple keys

On a running system, different software packages might be signed by
different parties.  Support verifying signatures in the measurement
list using multiple public keys(eg.  -k "key1, key2, ...").

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
This commit is contained in:
Mimi Zohar 2018-01-16 23:31:49 -05:00
parent 838b08b449
commit 9c79b7de72
4 changed files with 76 additions and 6 deletions

2
README
View File

@ -31,7 +31,7 @@ COMMANDS
ima_sign [--sigfile] [--key key] [--pass password] file
ima_verify file
ima_hash file
ima_measurement file
ima_measurement [--key "key1, key2, ..."] file
ima_fix [-t fdsxm] path
sign_hash [--key key] [--pass password]
hmac [--imahash | --imasig ] file

View File

@ -1419,6 +1419,10 @@ static int ima_measurement(const char *file)
return -1;
}
/* Support multiple public keys */
if (params.keyfile)
init_public_keys(params.keyfile);
while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
ima_extend_pcr(pcr, entry.header.digest, SHA_DIGEST_LENGTH);

View File

@ -205,5 +205,6 @@ int key2bin(RSA *key, unsigned char *pub);
int sign_hash(const char *algo, const unsigned char *hash, int size, const char *keyfile, const char *keypass, unsigned char *sig);
int verify_hash(const unsigned char *hash, int size, unsigned char *sig, int siglen);
int ima_verify_signature(const char *file, unsigned char *sig, int siglen);
void init_public_keys(const char *keyfiles);
#endif

View File

@ -409,6 +409,61 @@ int verify_hash_v1(const unsigned char *hash, int size, unsigned char *sig, int
return 0;
}
struct public_key_entry {
struct public_key_entry *next;
uint32_t keyid;
char name[9];
RSA *key;
};
static struct public_key_entry *public_keys = NULL;
static RSA *find_keyid(uint32_t keyid)
{
struct public_key_entry *entry;
for (entry = public_keys; entry != NULL; entry = entry->next) {
if (entry->keyid == keyid)
return entry->key;
}
return NULL;
}
void init_public_keys(const char *keyfiles)
{
struct public_key_entry *entry;
char *tmp_keyfiles;
char *keyfile;
int i = 1;
tmp_keyfiles = strdup(keyfiles);
while ((keyfile = strsep(&tmp_keyfiles, ", \t")) != NULL) {
if (!keyfile)
break;
if ((*keyfile == '\0') || (*keyfile == ' ') ||
(*keyfile == '\t'))
continue;
entry = malloc(sizeof(struct public_key_entry));
if (!entry) {
perror("malloc");
break;
}
entry->key = read_pub_key(keyfile, 1);
if (!entry->key) {
free(entry);
continue;
}
calc_keyid_v2(&entry->keyid, entry->name, entry->key);
sprintf(entry->name, "%x", __be32_to_cpup(&entry->keyid));
log_info("key %d: %s %s\n", i++, entry->name, keyfile);
entry->next = public_keys;
public_keys = entry;
}
}
int verify_hash_v2(const unsigned char *hash, int size, unsigned char *sig, int siglen, const char *keyfile)
{
int err, len;
@ -420,12 +475,22 @@ int verify_hash_v2(const unsigned char *hash, int size, unsigned char *sig, int
log_info("hash: ");
log_dump(hash, size);
key = read_pub_key(keyfile, 1);
if (!key)
return 1;
if (public_keys) {
key = find_keyid(hdr->keyid);
if (!key) {
log_err("Unknown keyid: %x\n",
__be32_to_cpup(&hdr->keyid));
return -1;
}
} else {
key = read_pub_key(keyfile, 1);
if (!key)
return 1;
}
err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr), out, key, RSA_PKCS1_PADDING);
RSA_free(key);
err = RSA_public_decrypt(siglen - sizeof(*hdr), sig + sizeof(*hdr),
out, key, RSA_PKCS1_PADDING);
if (err < 0) {
log_err("RSA_public_decrypt() failed: %d\n", err);
return 1;