mirror of
https://git.code.sf.net/p/linux-ima/ima-evm-utils
synced 2025-04-28 14:43:37 +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:
parent
838b08b449
commit
9c79b7de72
2
README
2
README
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user