@@ -909,7 +909,7 @@ static int verify_evm(const char *file)
return mdlen;
assert(mdlen <= sizeof(hash));
- return verify_hash(file, hash, mdlen, sig + 1, len - 1);
+ return verify_hash(file, hash, mdlen, sig, len);
}
static int cmd_verify_evm(struct command *cmd)
@@ -1572,7 +1572,8 @@ void ima_ng_show(struct template_entry *entry)
fieldp += field_len;
total_len -= field_len;
- if (!strcmp(entry->name, "ima-sig")) {
+ if (!strcmp(entry->name, "ima-sig") ||
+ !strcmp(entry->name, "ima-sigv2")) {
/* get signature */
field_len = *(uint32_t *)fieldp;
fieldp += sizeof(field_len);
@@ -1618,11 +1619,17 @@ void ima_ng_show(struct template_entry *entry)
log_info(" ");
log_dump(sig, sig_len);
}
+
+ /*
+ * Either verify the signature against the hash contained in
+ * the measurement list or calculate the hash.
+ */
if (verify_list_sig)
err = ima_verify_signature(path, sig, sig_len,
digest, digest_len);
else
err = ima_verify_signature(path, sig, sig_len, NULL, 0);
+
if (!err && imaevm_params.verbose > LOG_INFO)
log_info("%s: verification is OK\n", path);
} else {
@@ -534,11 +534,21 @@ int calc_hash_sigv3(enum evm_ima_xattr_type type, const char *algo,
return -EINVAL;
}
- if ((hash_algo = imaevm_get_hash_algo(algo)) < 0) {
- log_err("Hash algorithm %s not supported\n", algo);
- return -EINVAL;
+ /*
+ * Calculating the hash is based on the fsverity hash algorithm,
+ * while verifying the signature is based on the hash algorithm
+ * contained in the signature header.
+ */
+ if (algo) {
+ if ((hash_algo = imaevm_get_hash_algo(algo)) < 0) {
+ log_err("Hash algorithm %s not supported\n", algo);
+ return -EINVAL;
+ }
+ file_id.hash_algorithm = hash_algo;
+ } else {
+ algo = imaevm_params.hash_algo;
+ file_id.hash_algorithm = imaevm_get_hash_algo(algo);
}
- file_id.hash_algorithm = hash_algo;
md = EVP_get_digestbyname(algo);
if (!md) {
@@ -622,7 +632,7 @@ int imaevm_hash_algo_from_sig(unsigned char *sig)
default:
return -1;
}
- } else if (sig[0] == DIGSIG_VERSION_2) {
+ } else if (sig[0] == DIGSIG_VERSION_2 || sig[0] == DIGSIG_VERSION_3) {
hashalgo = ((struct signature_v2_hdr *)sig)->hash_algo;
if (hashalgo >= PKEY_HASH__LAST)
return -1;
@@ -634,8 +644,11 @@ int imaevm_hash_algo_from_sig(unsigned char *sig)
int verify_hash(const char *file, const unsigned char *hash, int size, unsigned char *sig,
int siglen)
{
+ unsigned char sigv3_hash[MAX_DIGEST_SIZE];
+ int ret;
+
/* Get signature type from sig header */
- if (sig[0] == DIGSIG_VERSION_1) {
+ if (sig[1] == DIGSIG_VERSION_1) {
const char *key = NULL;
/* Read pubkey from RSA key */
@@ -643,9 +656,17 @@ int verify_hash(const char *file, const unsigned char *hash, int size, unsigned
key = "/etc/keys/pubkey_evm.pem";
else
key = imaevm_params.keyfile;
- return verify_hash_v1(file, hash, size, sig, siglen, key);
- } else if (sig[0] == DIGSIG_VERSION_2) {
- return verify_hash_v2(file, hash, size, sig, siglen);
+ return verify_hash_v1(file, hash, size, sig + 1, siglen - 1,
+ key);
+ } else if (sig[1] == DIGSIG_VERSION_2) {
+ return verify_hash_v2(file, hash, size, sig + 1, siglen - 1);
+ } else if (sig[1] == DIGSIG_VERSION_3) {
+ ret = calc_hash_sigv3(sig[0], NULL, hash, sigv3_hash);
+ if (ret < 0)
+ return ret;
+
+ return verify_hash_v2(file, sigv3_hash, size, sig + 1,
+ siglen - 1);
} else
return -1;
}
@@ -656,11 +677,16 @@ int ima_verify_signature(const char *file, unsigned char *sig, int siglen,
unsigned char hash[MAX_DIGEST_SIZE];
int hashlen, sig_hash_algo;
- if (sig[0] != EVM_IMA_XATTR_DIGSIG) {
+ if ((sig[0] != EVM_IMA_XATTR_DIGSIG) && (sig[0] != IMA_VERITY_DIGSIG)) {
log_err("%s: xattr ima has no signature\n", file);
return -1;
}
+ if (!digest && sig[0] == IMA_VERITY_DIGSIG) {
+ log_err("%s: calculating the fs-verity digest is not supported\n", file);
+ return -1;
+ }
+
sig_hash_algo = imaevm_hash_algo_from_sig(sig + 1);
if (sig_hash_algo < 0) {
log_err("%s: Invalid signature\n", file);
@@ -674,14 +700,14 @@ int ima_verify_signature(const char *file, unsigned char *sig, int siglen,
* measurement list, not by calculating the local file digest.
*/
if (digestlen > 0)
- return verify_hash(file, digest, digestlen, sig + 1, siglen - 1);
+ return verify_hash(file, digest, digestlen, sig, siglen);
hashlen = ima_calc_hash(file, hash);
if (hashlen <= 1)
return hashlen;
assert(hashlen <= sizeof(hash));
- return verify_hash(file, hash, hashlen, sig + 1, siglen - 1);
+ return verify_hash(file, hash, hashlen, sig, siglen);
}
/*
ima-evm-utils does not attempt to calculate or even read the fs-verity file hash, but can verify the fs-verity signature based on the fsverity file hash, both contained in the measurement list record. For the time being only fs-verity supports signature format v3 (sigv3). To differentiate between the existing IMA and fs-verity file signatures, modify the verify_hash() 'sig' argument to be a pointer to the entire xattr, including the xattr type. Example: evmctl ima_measurement --key <DER encoded public key> \ --verify-sig /sys/kernel/security/ima/binary_runtime_measurements Signed-off-by: Mimi Zohar <zohar@linux.ibm.com> --- src/evmctl.c | 11 +++++++++-- src/libimaevm.c | 50 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 14 deletions(-)