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_sign [--sigfile] [--key key] [--pass password] file
|
||||||
ima_verify file
|
ima_verify file
|
||||||
ima_hash file
|
ima_hash file
|
||||||
ima_measurement file
|
ima_measurement [--key "key1, key2, ..."] file
|
||||||
ima_fix [-t fdsxm] path
|
ima_fix [-t fdsxm] path
|
||||||
sign_hash [--key key] [--pass password]
|
sign_hash [--key key] [--pass password]
|
||||||
hmac [--imahash | --imasig ] file
|
hmac [--imahash | --imasig ] file
|
||||||
|
@ -1419,6 +1419,10 @@ static int ima_measurement(const char *file)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Support multiple public keys */
|
||||||
|
if (params.keyfile)
|
||||||
|
init_public_keys(params.keyfile);
|
||||||
|
|
||||||
while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
|
while (fread(&entry.header, sizeof(entry.header), 1, fp)) {
|
||||||
ima_extend_pcr(pcr, entry.header.digest, SHA_DIGEST_LENGTH);
|
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 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 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);
|
int ima_verify_signature(const char *file, unsigned char *sig, int siglen);
|
||||||
|
void init_public_keys(const char *keyfiles);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -409,6 +409,61 @@ int verify_hash_v1(const unsigned char *hash, int size, unsigned char *sig, int
|
|||||||
return 0;
|
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 verify_hash_v2(const unsigned char *hash, int size, unsigned char *sig, int siglen, const char *keyfile)
|
||||||
{
|
{
|
||||||
int err, len;
|
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_info("hash: ");
|
||||||
log_dump(hash, size);
|
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);
|
key = read_pub_key(keyfile, 1);
|
||||||
if (!key)
|
if (!key)
|
||||||
return 1;
|
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) {
|
if (err < 0) {
|
||||||
log_err("RSA_public_decrypt() failed: %d\n", err);
|
log_err("RSA_public_decrypt() failed: %d\n", err);
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user